#include "c-threads.h"

#define __TEST__ 0


#if defined(_WIN32) || defined(__WIN32__) /* windows threads expected */
#include <windows.h>

#define go_to_sleep(a) Sleep(a*1000)

typedef struct {
  /*LPDWORD         threadId;*/
  HANDLE          handle;
  void           *data;
  t_c_thread_func f;
  int             result;
} t_c_thread_win32;


static DWORD WINAPI ThreadProc(LPVOID lpParam)
{
  t_c_thread_win32 *H=(t_c_thread_win32 *) lpParam;
  H->result=H->f(H->data);
  ExitThread(0);
}


t_c_thread_id c_thread_create(t_c_thread_func f,void *data)
{
  t_c_thread_win32 *H=(t_c_thread_win32 *) malloc(sizeof(t_c_thread_win32));
  H->f=f;
  H->data=data;

  H->handle=CreateThread(NULL,
			 C_THREAD_STACK_SIZE*1024,
			 ThreadProc,
			 H,
			 0,
			 NULL
			 /*&H->threadId*/
			 );
  return (t_c_thread_id) H;  
}

int c_thread_join(t_c_thread_id h)
{ 
  int result;
  t_c_thread_win32 *H=(t_c_thread_win32 *) h;
  WaitForSingleObject(H->handle,INFINITE);
  result=H->result;
  free(H);
  return result;
}


#else /* posix threads expected */

#define go_to_sleep(a) sleep(a)

#include <pthread.h>

typedef struct {
  pthread_t        thread;
  int              errorcode;
  t_c_thread_func  f;
  void            *data;
  int              result;
} t_c_thread_posix;


static
void *thread_func(void * data)
{
  t_c_thread_posix *H=(t_c_thread_posix *) data;
  H->result=H->f(H->data);
  pthread_exit(data);
  return data;
}

t_c_thread_id c_thread_create(t_c_thread_func f,void *data)
{
  t_c_thread_posix *H=(t_c_thread_posix *) malloc(sizeof(t_c_thread_posix));

  H->f=f;
  H->data=data;

  H->errorcode=pthread_create(&H->thread,
			      NULL,
			      thread_func,
			      (void *) H);
  return (t_c_thread_id) H;
}

int c_thread_join(t_c_thread_id h)
{
  int result;
  t_c_thread_posix *H=(t_c_thread_posix *) h;
  pthread_join(H->thread,NULL);
  result=H->result;
  free(H);
  return result;
}


#endif

/*
=head1 Info

S<C<Author(s):>> Hans Oesterholt (hansatelementalprogrammingdotorgextension).E<lb>
S<C<Copyright:>> (c) 2005.E<lb>
S<C<License  :>> L<Elemental Programming Artistic License|http://www.elemental-programming.org/epwiki/ep_license.html>.E<lb>
S<C<File     :>> c-thread.c$Revision: 1.1 $

=cut
*/


/* test code */

#if (__TEST__==1)

int f(void *data)
{
  int *c=(int *) data;
  int i;
  *c=-1;
  for(i=0;i<10;i++) {
    go_to_sleep(1);
    printf("i=%d\n",i);
  }
  *c=i*10;
  return i;
}

int main()
{
  int C;
  int i,result;
  t_c_thread_id I=c_thread_create(f,&C);

  for(i=0;i<5;i++) {
    go_to_sleep(1);
    printf("mi=%d\n",i);
  }

  result=c_thread_join(I);
  printf("C=%d\n",C);
  printf("result=%d\n",result);
  
  return 0;
}

#endif

