#ifndef TH_THREAD_INC #define TH_THREAD_INC #include #include /*#include "TH.h" */ #include "THThread.h" #if defined(USE_PTHREAD_THREADS) #include #elif defined(USE_WIN32_THREADS) /* very basic emulation to suit our needs */ #include #include 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