#ifndef _TTHREAD_H_ #define _TTHREAD_H_ #include "sysenv.h" #include #include #if _OS_WIN #include typedef DWORD TID; typedef CRITICAL_SECTION MUTEX; typedef CONDITION_VARIABLE COND; #elif _OS_LINUX #include #include #include typedef pthread_t TID; typedef pthread_mutex_t MUTEX; typedef pthread_cond_t COND; #else #error "Not Supported Operator System" #endif #ifndef ZZY_SLEEP #define ZZY_SLEEP #if _OS_WIN #define sleeps(s) Sleep(s*1000) #define sleepms(ms) Sleep(ms) #elif _OS_LINUX #define sleeps(s) sleep(s) #define sleepms(ms) usleep(ms*1000) #endif #endif #ifdef __cplusplus extern "C" { #endif enum ERR_THREAD { ERR_THREAD_SUCCESS, ERR_THREAD_CREATE, ERR_THREAD_JOIN, ERR_THREAD_WIN_CLOSE_HANDLE, //ERR_THREAD_WIN_OPEN_THREAD, ERR_THREAD_MUTEX_INIT, ERR_THREAD_MUTEX_DESTROY, ERR_THREAD_MUTEX_LOCK, ERR_THREAD_MUTEX_UNLOCK, ERR_THREAD_COND_INIT, ERR_THREAD_COND_DESTROY, ERR_THREAD_COND_SINGAL, ERR_THREAD_COND_BROADCAST, ERR_THREAD_COND_WAIT, ERR_THREAD_COND_TIMEDWAIT, ERR_THREAD_COND_TIME_OUT, ERR_THREAD_ENUM_END }; static inline int thread_create(TID* tid, void(*start_routine)(void*), void* arg); static inline void thread_exit(void); static inline int thread_join(TID tid); static inline TID thread_self(void); static inline int thread_mutex_init(MUTEX* mutex); static inline int thread_mutex_destroy(MUTEX* mutex); static inline int thread_mutex_lock(MUTEX* mutex); static inline int thread_mutex_unlock(MUTEX* mutex); static inline int thread_cond_init(COND* cond); static inline int thread_cond_destroy(COND* cond); static inline int thread_cond_singal(COND* cond); static inline int thread_cond_broadcast(COND* cond); static inline int thread_cond_wait(COND* cond, MUTEX* mutex); static inline int thread_cond_timedwait(COND* cond, MUTEX* mutex, int ms); static inline int tprintf(MUTEX* mutex, const char* format, ...); static inline int tfprintf(MUTEX* mutex, FILE* const stream, const char* format, ...); static inline int tsprintf(MUTEX* mutex, char* const buffer, const char* format, ...); static inline int tsnprintf(MUTEX* mutex, char* const buffer, const size_t buffer_count, const char* format, ...); static inline int tvprintf(MUTEX* mutex, const char* format, va_list arglist); static inline int tvfprintf(MUTEX* mutex, FILE* const stream, const char* format, va_list arglist); static inline int tvsprintf(MUTEX* mutex, char* const buffer, const char* format, va_list arglist); static inline int tvsnprintf(MUTEX* mutex, char* const buffer, const size_t buffer_count, const char* format, va_list arglist); static inline int thread_create(TID* tid, void(*start_routine)(void*), void* arg) { #if _OS_WIN HANDLE h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, arg, 0, (LPDWORD)tid); if (h == NULL) { return ERR_THREAD_CREATE; } if (!CloseHandle(h)) { return ERR_THREAD_WIN_CLOSE_HANDLE; } #elif _OS_LINUX TID ttid; if (pthread_create(&ttid, NULL, (void*(*)(void*))start_routine, arg) != 0) { return ERR_THREAD_CREATE; } if (tid) *tid = ttid; #endif return ERR_THREAD_SUCCESS; } static inline void thread_exit(void) { #if _OS_WIN ThreadExit(0); #elif _OS_LINUX pthread_exit(NULL); #endif } static inline int thread_join(TID tid) { #if _OS_WIN HANDLE h = OpenThread(THREAD_ALL_ACCESS, 0, tid); if (h != NULL) { if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED) { return -ERR_THREAD_JOIN; } if (!CloseHandle(h)) { return -ERR_THREAD_WIN_CLOSE_HANDLE; } } #elif _OS_LINUX if (pthread_join(tid, NULL) != 0) { return -ERR_THREAD_JOIN; } #endif return ERR_THREAD_SUCCESS; } static inline TID thread_self(void) { #if _OS_WIN return GetCurrentThreadId(); #elif _OS_LINUX return pthread_self(); #endif } // mutex part static inline int thread_mutex_init(MUTEX* mutex) { #if _OS_WIN InitializeCriticalSection(mutex); #elif _OS_LINUX if (pthread_mutex_init(mutex, NULL) != 0) { return -ERR_THREAD_MUTEX_INIT; } #endif return ERR_THREAD_SUCCESS; } static inline int thread_mutex_destroy(MUTEX* mutex) { #if _OS_WIN #elif _OS_LINUX if (pthread_mutex_destroy(mutex) != 0) { return -ERR_THREAD_MUTEX_DESTROY; } #endif return ERR_THREAD_SUCCESS; } static inline int thread_mutex_lock(MUTEX* mutex) { #if _OS_WIN EnterCriticalSection(mutex); #elif _OS_LINUX if (pthread_mutex_lock(mutex) != 0) { return -ERR_THREAD_MUTEX_LOCK; } #endif return ERR_THREAD_SUCCESS; } static inline int thread_mutex_unlock(MUTEX* mutex) { #if _OS_WIN LeaveCriticalSection(mutex); #elif _OS_LINUX if (pthread_mutex_unlock(mutex) != 0) { return -ERR_THREAD_MUTEX_UNLOCK; } #endif return ERR_THREAD_SUCCESS; } //cond part static inline int thread_cond_init(COND* cond) { #if _OS_WIN InitializeConditionVariable(cond); if (cond == NULL) { return -ERR_THREAD_COND_INIT; } #elif _OS_LINUX if (pthread_cond_init(cond, NULL) != 0) { return -ERR_THREAD_COND_INIT; } #endif return ERR_THREAD_SUCCESS; } static inline int thread_cond_destroy(COND* cond) { #if _OS_WIN #elif _OS_LINUX if (pthread_cond_destroy(cond) != 0) { return -ERR_THREAD_COND_DESTROY; } #endif return ERR_THREAD_SUCCESS; } static inline int thread_cond_singal(COND* cond) { #if _OS_WIN WakeConditionVariable(cond); #elif _OS_LINUX if (pthread_cond_signal(cond) != 0) { return -ERR_THREAD_COND_SINGAL; } #endif return ERR_THREAD_SUCCESS; } static inline int thread_cond_broadcast(COND* cond) { #if _OS_WIN WakeAllConditionVariable(cond); #elif _OS_LINUX if (pthread_cond_broadcast(cond) != 0) { return -ERR_THREAD_COND_BROADCAST; } #endif return ERR_THREAD_SUCCESS; } static inline int thread_cond_wait(COND* cond, MUTEX* mutex) { #if _OS_WIN if (SleepConditionVariableCS(cond, mutex, INFINITE) != 0) { return -ERR_THREAD_COND_WAIT; } #elif _OS_LINUX if (pthread_cond_wait(cond, mutex) != 0) { return -ERR_THREAD_COND_WAIT; } #endif return ERR_THREAD_SUCCESS; } static inline int thread_cond_timedwait(COND* cond, MUTEX* mutex, int ms) { #if _OS_WIN int res = SignalObjectAndWait(cond, mutex, ms, 0); if (res == WAIT_TIMEOUT) { return -ERR_THREAD_COND_TIME_OUT; } if (res == WAIT_FAILED) { return -ERR_THREAD_COND_TIMEDWAIT; } #elif _OS_LINUX struct timespec outtime; clock_gettime(CLOCK_MONOTONIC, &outtime); outtime.tv_sec += ms/1000; outtime.tv_nsec += (ms % 1000) * 1000 * 1000; int res = pthread_cond_timedwait(cond, mutex, &outtime); if (res == ETIMEDOUT) { return -ERR_THREAD_COND_TIME_OUT; } if (res != 0) { return -ERR_THREAD_COND_TIMEDWAIT; } #endif return ERR_THREAD_SUCCESS; } // thread safety stdio static inline int tprintf(MUTEX* mutex, const char* format, ...) { va_list var; va_start(var, format); int res = tvprintf(mutex, format, var); va_end(var); return res; } static inline int tvprintf(MUTEX* mutex, const char* format, va_list arglist) { thread_mutex_lock(mutex); int res = vprintf(format, arglist); thread_mutex_unlock(mutex); return res; } static inline int tfprintf(MUTEX* mutex, FILE *const stream, const char* format, ...) { va_list var; va_start(var, format); int res = tvfprintf(mutex, stream, format, var); va_end(var); return res; } static inline int tvfprintf(MUTEX* mutex, FILE* const stream, const char* format, va_list arglist) { thread_mutex_lock(mutex); int res = vfprintf(stream, format, arglist); thread_mutex_unlock(mutex); return res; } static inline int tsprintf(MUTEX* mutex, char* const buffer, const char* format, ...) { va_list var; va_start(var, format); int res = tvsprintf(mutex, buffer, format, var); va_end(var); return res; } static inline int tvsprintf(MUTEX* mutex, char* const buffer, const char* format, va_list arglist) { thread_mutex_lock(mutex); int res = vsprintf(buffer, format, arglist); thread_mutex_unlock(mutex); return res; } static inline int tsnprintf(MUTEX* mutex, char* const buffer, const size_t buffer_count, const char* format, ...) { va_list var; va_start(var, format); int res = tvsnprintf(mutex, buffer, buffer_count, format, var); va_end(var); return res; } static inline int tvsnprintf(MUTEX* mutex, char* const buffer, const size_t buffer_count, const char* format, va_list arglist) { thread_mutex_lock(mutex); int res = vsnprintf(buffer,buffer_count, format, arglist); thread_mutex_unlock(mutex); return res; } #ifdef __cplusplus } #endif #endif //_TTHREAD_H_