/* 
 * Copyright (C) 2000-2001 Computer & Communications Research Laboratories,
 *			   Industrial Technology Research Institute
 */
/*
 * lowSync.c
 *
 * $Id: lowSync.c,v 1.17 2001/06/14 09:50:55 hcc Exp $
 */

#define _POSIX_C_SOURCE 199309L /* struct timespec */

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

struct lowMutexObj {
	mutexType		myType_;
	int			key_;
#if defined(UNIX)
	pthread_mutex_t		*pCS_;
	pthread_mutexattr_t	*pCSAtt_;
#elif defined(WIN32)
	LPCRITICAL_SECTION	pCS_;
	HANDLE			hmutex_;
#endif		
};

lowMutex	lowMutexNew(mutexType mtype, int key)
{
	lowMutex	this_ = NULL;

	if( mtype!=MUTEX_INTERPROCESS && mtype!=MUTEX_INTERTHREAD )
		return NULL;

	this_ = (lowMutex)malloc(sizeof(struct lowMutexObj));
	if(!this_)
		return NULL;

	this_->myType_ = mtype;
	this_->key_ = key;
	

	if( mtype==MUTEX_INTERTHREAD ) {
#if defined(UNIX)
		this_->pCSAtt_ = NULL;
		this_->pCS_ = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
		if( pthread_mutex_init(this_->pCS_,NULL)!=0 ) {
			free(this_->pCS_);
			free(this_);
			return NULL;
		}
#elif defined(WIN32)
		this_->hmutex_ = NULL; /* unused, set to NULL */
		this_->pCS_ = (LPCRITICAL_SECTION)malloc(sizeof(CRITICAL_SECTION));
		InitializeCriticalSection(this_->pCS_);
#endif
	}
	else if ( mtype==MUTEX_INTERPROCESS ) {
#if defined(UNIX)
		/* to be implemented */
#elif defined(WIN32)
		char	key_temp[5] = {0,0,0,0,0};
		
		this_->pCS_ = NULL;
		*((int*)key_temp) = this_->key_;
		this_->hmutex_ = CreateMutex(NULL,FALSE,key_temp);
		if( this_->hmutex_==NULL ) {
			free(this_);
			return NULL;
		}
#endif
	}

	return this_;
}


int		lowMutexLock(lowMutex mutex)
{
	if(!mutex)
		return -1;

	if( mutex->myType_==MUTEX_INTERTHREAD ) {
#if defined(UNIX)
		if(!mutex->pCS_)
			return -1;	
		return pthread_mutex_lock(mutex->pCS_);
#elif defined(WIN32)
		if(!mutex->pCS_)
			return -1;
		EnterCriticalSection(mutex->pCS_);
#endif
	}
	else if ( mutex->myType_==MUTEX_INTERPROCESS ) {
#if defined(UNIX)
		/* to be implemented */
#elif defined(WIN32)
		if(!mutex->hmutex_)
			return -1;
		if( WaitForSingleObject(mutex->hmutex_,INFINITE)==WAIT_FAILED )
			return -1;	
#endif
	}

	return 0;
}


int		lowMutexUnlock(lowMutex mutex)
{
	if(!mutex)
		return -1;

	if( mutex->myType_==MUTEX_INTERTHREAD ) {
#if defined(UNIX)
		if(!mutex->pCS_)
			return -1;
			
		return pthread_mutex_unlock(mutex->pCS_);
#elif defined(WIN32)
		if(!mutex->pCS_)
			return -1;
		LeaveCriticalSection(mutex->pCS_);
#endif
	}
	else if ( mutex->myType_==MUTEX_INTERPROCESS ) {
#if defined(UNIX)
		/* to be implemented */
#elif defined(WIN32)
		if(!mutex->hmutex_)
			return -1;
		if( !ReleaseMutex(mutex->hmutex_) )
			return -1;
#endif
	}

	return 0;
}


void		lowMutexFree(lowMutex mutex)
{
	if(!mutex)
		return;

	if( mutex->myType_==MUTEX_INTERTHREAD ) {
#if defined(UNIX)
		if(mutex->pCS_) {
			pthread_mutex_lock(mutex->pCS_);
			pthread_mutex_unlock(mutex->pCS_);
			pthread_mutex_destroy(mutex->pCS_);
			free(mutex->pCS_);
			mutex->pCS_ = NULL;
		}
#elif defined(WIN32)
		if(mutex->pCS_) {	
			EnterCriticalSection(mutex->pCS_);
			LeaveCriticalSection(mutex->pCS_);			
			DeleteCriticalSection(mutex->pCS_);
			free(mutex->pCS_);
			mutex->pCS_ = NULL;
		}
#endif
	}
	else if ( mutex->myType_==MUTEX_INTERPROCESS ) {
#if defined(UNIX)
		/* to be implemented */
#elif defined(WIN32)
		if(mutex->hmutex_) {
			CloseHandle(mutex->hmutex_);
			mutex->hmutex_ = NULL;
		}
#endif
	}

	free(mutex);
}

