/* 
 * Copyright (C) 2000-2001 Computer & Communications Research Laboratories,
 *			   Industrial Technology Research Institute
 */
/*
 * lowSync.c
 *
 * $Id: thread.c,v 1.13 2001/06/21 02:56:09 hcc Exp $
 */
#define _POSIX_C_SOURCE 199309L /* struct timespec */

#include <stdlib.h>
#if defined(UNIX)
#include <time.h>
#include <sys/types.h>
#include <pthread.h>
#elif defined(WIN32)
#include <process.h>
#endif

#include "common.h"
#include "thread.h"

struct threadObj {
#if defined(UNIX)
	pthread_t	threadID_;
	pthread_attr_t	attr_;
#elif defined(WIN32)
	HANDLE	 	hthread_;
	UINT32		threadID_;
#endif
};

thread	threadCreate(void*(*thread_routine)(void*),void *arg)
{
	thread	this_ = (thread)malloc(sizeof(struct threadObj));
	int	ret;

#if defined(UNIX)
	/* initialize attr with default attributes */
        pthread_attr_init(&this_->attr_); 
        ret = pthread_create(&this_->threadID_, &this_->attr_, thread_routine, arg);
        if( ret!=0 ) {
        	free(this_);
        	/*set return code here*/
        	return NULL;	
        }
#elif defined(WIN32)
	this_->hthread_ = (HANDLE)_beginthreadex(NULL,0,
				(unsigned (__stdcall*)(void*))thread_routine,
				arg,CREATE_SUSPENDED,&this_->threadID_);
	if( this_->hthread_==INVALID_HANDLE_VALUE ) {
		free(this_);
		return NULL;
	}
	ret = ResumeThread(this_->hthread_);
	if( ret==-1 ) {
		CloseHandle(this_->hthread_);
		free(this_);
		return NULL;
	}
#endif	
	return this_;
}


RETCODE threadJoin(thread this_)
{
	int 	ret;
#if defined(UNIX)
	int* 	rot;
#endif	
	
	if(!this_)	return -1;
	
#if defined(UNIX)
	ret = pthread_join(this_->threadID_,(void**)&rot);
	if( ret!=0 ) {
		/*if( ret==ESRCH )
			return -2;*/
		return -1;
	}
#elif defined(WIN32)
	ret = WaitForSingleObject(this_->hthread_,INFINITE);
	if( ret==WAIT_FAILED ) {
		return -1;
	}
	CloseHandle(this_->hthread_);
#endif	
	free(this_);
	return 0;	
}

RETCODE threadCancel(thread this_)
{
	int 	ret;

	if(!this_)	return -1;
	
#if defined(UNIX)
	ret = pthread_cancel(this_->threadID_);
	if( ret!=0 ) {
		return -1;
	}
#elif defined(WIN32)
	ret = TerminateThread(this_->hthread_,0);
	if( ret==FALSE ) {
		return -1;
	}
	CloseHandle(this_->hthread_);
#endif		
	free(this_);
	return 0;
}


