#ifndef TH_THREAD_INC
#define TH_THREAD_INC
#include <stdlib.h>
#include <string.h>
/*#include "TH.h" */
#include "THThread.h"
#if defined(USE_PTHREAD_THREADS)
#include <pthread.h>
#elif defined(USE_WIN32_THREADS)
/* very basic emulation to suit our needs */
#include <process.h>
#include <windows.h>
typedef HANDLE pthread_t;
typedef DWORD pthread_attr_t;
typedef HANDLE pthread_mutex_t;
typedef HANDLE pthread_cond_t;
static int pthread_create(pthread_t *restrict thread,
const pthread_attr_t *restrict attr, void *(*start_routine)(void *),
void *restrict arg)
{
*thread = (HANDLE)_beginthreadex(NULL, 0, (THREAD_FUNCTION)start_routine, arg, 0, NULL);
return (int)(*thread == NULL);
}
static int pthread_join(pthread_t thread, void **value_ptr)
{
return ((WaitForSingleObject((thread), INFINITE) != WAIT_OBJECT_0) || !CloseHandle(thread));
}
static int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr)
{
*mutex = CreateMutex(NULL, FALSE, NULL);
return (int)(*mutex == NULL);
}
static int pthread_mutex_lock(pthread_mutex_t *mutex)
{
return WaitForSingleObject(*mutex, INFINITE) == 0;
}
static int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
return ReleaseMutex(*mutex) == 0;
}
static int pthread_mutex_destroy(pthread_mutex_t *mutex)
{
return CloseHandle(*mutex) == 0;
}
static int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr)
{
*cond = CreateEvent(NULL, FALSE, FALSE, NULL);
return (int)(*cond == NULL);
}
static int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex)
{
SignalObjectAndWait(*mutex, *cond, INFINITE, FALSE);
return WaitForSingleObject(*mutex, INFINITE) == 0;
}
static int pthread_cond_destroy(pthread_cond_t *cond)
{
return CloseHandle(*cond) == 0;
}
int pthread_cond_signal(pthread_cond_t *cond)
{
return SetEvent(*cond) == 0;
}
#else
#error no thread system available
#endif
typedef struct THThread_ {
pthread_t id;
int (*func)(void*);
void* data;
int status;
} THThread;
typedef struct THMutex_{
pthread_mutex_t id;
int refcount;
} THMutex;
typedef struct THCondition_ {
pthread_cond_t id;
int refcount;
} THCondition;
typedef struct THSemaphore_ {
pthread_mutex_t mutex_;
pthread_cond_t cond_;
int counter_;
int refcount;
}THSemaphore;
static void* thread_closure(void *data)
{
THThread *thread = data;
thread->status = thread->func(thread->data);
return NULL;
}
THThread* THThread_new(int (*func)(void*), void *data)
{
THThread *self = malloc(sizeof(THThread));
self->func = func;
self->data = data;
self->status = 0;
if(!self)
return NULL;
if(pthread_create(&self->id, NULL, thread_closure, self)) {
free(self);
return NULL;
}
return self;
}
long THThread_id(THThread *self)
{
return (long)(self);
}
int THThread_free(THThread *self)
{
int status = 1;
if(self) {
if(pthread_join(self->id, NULL))
return 1;
status = self->status;
free(self);
self = NULL;
}
return status;
}
THMutex* THMutex_new(void)
{
THMutex *self = malloc(sizeof(THMutex));
if(!self)
return NULL;
if(pthread_mutex_init(&self->id, NULL) != 0) {
free(self);
return NULL;
}
self->refcount = 1;
return self;
}
THMutex* THMutex_newWithId(long id)
{
THMutex *self = (THMutex*)id;
__sync_fetch_and_add(&self->refcount, 1);
return self;
}
long THMutex_id(THMutex *self)
{
return (long)(self);
}
int THMutex_lock(THMutex *self)
{
if(pthread_mutex_lock(&self->id) != 0)
return 1;
return 0;
}
int THMutex_trylock(THMutex *self)
{
if (pthread_mutex_trylock(&self->id) != 0)
return 1;
return 0;
}
int THMutex_unlock(THMutex *self)
{
if(pthread_mutex_unlock(&self->id) != 0)
return 1;
return 0;
}
void THMutex_free(THMutex *self)
{
if(self) {
if(__sync_fetch_and_add(&self->refcount, -1) == 1) {
pthread_mutex_destroy(&self->id);
free(self);
self = NULL;
}
}
}
THCondition* THCondition_new(void)
{
THCondition *self = malloc(sizeof(THCondition));
if(!self)
return NULL;
if(pthread_cond_init(&self->id, NULL)) {
free(self);
return NULL;
}
self->refcount = 1;
return self;
}
THCondition* THCondition_newWithId(long id)
{
THCondition *self = (THCondition*)id;
__sync_fetch_and_add(&self->refcount, 1);
return self;
}
long THCondition_id(THCondition *self)
{
return (long)(self);
}
int THCondition_signal(THCondition *self)
{
if(pthread_cond_signal(&self->id))
return 1;
return 0;
}
int THCondition_wait(THCondition *self, THMutex *mutex)
{
if(pthread_cond_wait(&self->id, &mutex->id))
return 1;
return 0;
}
void THCondition_free(THCondition *self)
{
if(self) {
if(__sync_fetch_and_add(&self->refcount, -1) == 1) {
pthread_cond_destroy(&self->id);
free(self);
self = NULL;
}
}
}
THSemaphore* THSemaphore_new(int initValue)
{
THSemaphore *self = malloc(sizeof(THSemaphore));
if(!self)
return NULL;
self->counter_ = initValue;
if(pthread_mutex_init(&self->mutex_, NULL) != 0)
{
free(self);
return NULL;
}
if(pthread_cond_init(&self->cond_, NULL) != 0)
{
free(self);
return NULL;
}
self->refcount = 1;
return self;
}
THSemaphore* THSemaphore_newWithId(long id)
{
THSemaphore *self = (THSemaphore*)id;
__sync_fetch_and_add(&self->refcount, 1);
return self;
}
long THSemaphore_id(THSemaphore *self)
{
return (long)(self);
}
int THSemaphore_wait(THSemaphore *self)
{
int ret = 0;
ret |= pthread_mutex_lock(&self->mutex_);
while (self->counter_ <= 0)
ret |= pthread_cond_wait(&self->cond_, &self->mutex_);
self->counter_--;
ret |= pthread_mutex_unlock(&self->mutex_);
return ret;
}
int THSemaphore_signal(THSemaphore *self)
{
int ret = 0;
ret |= pthread_mutex_lock(&self->mutex_);
self->counter_++;
ret |= pthread_cond_signal(&self->cond_);
ret |= pthread_mutex_unlock(&self->mutex_);
return ret;
}
int THSemaphore_trywait(THSemaphore *self)
{
int ret = 0;
int try_wait_succeeded = 1;
ret |= pthread_mutex_lock(&self->mutex_);
if (self->counter_ > 0) {
self->counter_--;
try_wait_succeeded = 0;
}
ret |= pthread_mutex_unlock(&self->mutex_);
return try_wait_succeeded;
}
void THSemaphore_free(THSemaphore *self)
{
if(self)
{
if(__sync_fetch_and_add(&self->refcount, -1) == 1)
{
pthread_mutex_destroy(&self->mutex_);
pthread_cond_destroy(&self->cond_);
free(self);
self = NULL;
}
}
}
#endif