TinyCThread 1.1
|
00001 /* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; -*- 00002 Copyright (c) 2012 Marcus Geelnard 00003 00004 This software is provided 'as-is', without any express or implied 00005 warranty. In no event will the authors be held liable for any damages 00006 arising from the use of this software. 00007 00008 Permission is granted to anyone to use this software for any purpose, 00009 including commercial applications, and to alter it and redistribute it 00010 freely, subject to the following restrictions: 00011 00012 1. The origin of this software must not be misrepresented; you must not 00013 claim that you wrote the original software. If you use this software 00014 in a product, an acknowledgment in the product documentation would be 00015 appreciated but is not required. 00016 00017 2. Altered source versions must be plainly marked as such, and must not be 00018 misrepresented as being the original software. 00019 00020 3. This notice may not be removed or altered from any source 00021 distribution. 00022 */ 00023 00024 #ifndef _TINYCTHREAD_H_ 00025 #define _TINYCTHREAD_H_ 00026 00050 /* Which platform are we on? */ 00051 #if !defined(_TTHREAD_PLATFORM_DEFINED_) 00052 #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) 00053 #define _TTHREAD_WIN32_ 00054 #else 00055 #define _TTHREAD_POSIX_ 00056 #endif 00057 #define _TTHREAD_PLATFORM_DEFINED_ 00058 #endif 00059 00060 /* Activate some POSIX functionality (e.g. clock_gettime and recursive mutexes) */ 00061 #if defined(_TTHREAD_POSIX_) 00062 #undef _FEATURES_H 00063 #if !defined(_GNU_SOURCE) 00064 #define _GNU_SOURCE 00065 #endif 00066 #if !defined(_POSIX_C_SOURCE) || ((_POSIX_C_SOURCE - 0) < 199309L) 00067 #undef _POSIX_C_SOURCE 00068 #define _POSIX_C_SOURCE 199309L 00069 #endif 00070 #if !defined(_XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 500) 00071 #undef _XOPEN_SOURCE 00072 #define _XOPEN_SOURCE 500 00073 #endif 00074 #endif 00075 00076 /* Generic includes */ 00077 #include <time.h> 00078 00079 /* Platform specific includes */ 00080 #if defined(_TTHREAD_POSIX_) 00081 #include <pthread.h> 00082 #elif defined(_TTHREAD_WIN32_) 00083 #ifndef WIN32_LEAN_AND_MEAN 00084 #define WIN32_LEAN_AND_MEAN 00085 #define __UNDEF_LEAN_AND_MEAN 00086 #endif 00087 #include <windows.h> 00088 #ifdef __UNDEF_LEAN_AND_MEAN 00089 #undef WIN32_LEAN_AND_MEAN 00090 #undef __UNDEF_LEAN_AND_MEAN 00091 #endif 00092 #endif 00093 00094 /* Workaround for missing TIME_UTC: If time.h doesn't provide TIME_UTC, 00095 it's quite likely that libc does not support it either. Hence, fall back to 00096 the only other supported time specifier: CLOCK_REALTIME (and if that fails, 00097 we're probably emulating clock_gettime anyway, so anything goes). */ 00098 #ifndef TIME_UTC 00099 #ifdef CLOCK_REALTIME 00100 #define TIME_UTC CLOCK_REALTIME 00101 #else 00102 #define TIME_UTC 0 00103 #endif 00104 #endif 00105 00106 /* Workaround for missing clock_gettime (most Windows compilers, afaik) */ 00107 #if defined(_TTHREAD_WIN32_) 00108 #define _TTHREAD_EMULATE_CLOCK_GETTIME_ 00109 /* Emulate struct timespec */ 00110 struct _ttherad_timespec { 00111 time_t tv_sec; 00112 long tv_nsec; 00113 }; 00114 #define timespec _ttherad_timespec 00115 00116 /* Emulate clockid_t */ 00117 typedef int _tthread_clockid_t; 00118 #define clockid_t _tthread_clockid_t 00119 00120 /* Emulate clock_gettime */ 00121 int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts); 00122 #define clock_gettime _tthread_clock_gettime 00123 #endif 00124 00125 00127 #define TINYCTHREAD_VERSION_MAJOR 1 00128 00129 #define TINYCTHREAD_VERSION_MINOR 1 00130 00131 #define TINYCTHREAD_VERSION (TINYCTHREAD_VERSION_MAJOR * 100 + TINYCTHREAD_VERSION_MINOR) 00132 00152 /* FIXME: Check for a PROPER value of __STDC_VERSION__ to know if we have C11 */ 00153 #if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) && !defined(_Thread_local) 00154 #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__) 00155 #define _Thread_local __thread 00156 #else 00157 #define _Thread_local __declspec(thread) 00158 #endif 00159 #endif 00160 00161 /* Macros */ 00162 #define TSS_DTOR_ITERATIONS 0 00163 00164 /* Function return values */ 00165 #define thrd_error 0 00166 #define thrd_success 1 00167 #define thrd_timeout 2 00168 #define thrd_busy 3 00169 #define thrd_nomem 4 00171 /* Mutex types */ 00172 #define mtx_plain 1 00173 #define mtx_timed 2 00174 #define mtx_try 4 00175 #define mtx_recursive 8 00176 00177 /* Mutex */ 00178 #if defined(_TTHREAD_WIN32_) 00179 typedef struct { 00180 CRITICAL_SECTION mHandle; /* Critical section handle */ 00181 int mAlreadyLocked; /* TRUE if the mutex is already locked */ 00182 int mRecursive; /* TRUE if the mutex is recursive */ 00183 } mtx_t; 00184 #else 00185 typedef pthread_mutex_t mtx_t; 00186 #endif 00187 00200 int mtx_init(mtx_t *mtx, int type); 00201 00205 void mtx_destroy(mtx_t *mtx); 00206 00215 int mtx_lock(mtx_t *mtx); 00216 00219 int mtx_timedlock(mtx_t *mtx, const struct timespec *ts); 00220 00229 int mtx_trylock(mtx_t *mtx); 00230 00236 int mtx_unlock(mtx_t *mtx); 00237 00238 /* Condition variable */ 00239 #if defined(_TTHREAD_WIN32_) 00240 typedef struct { 00241 HANDLE mEvents[2]; /* Signal and broadcast event HANDLEs. */ 00242 unsigned int mWaitersCount; /* Count of the number of waiters. */ 00243 CRITICAL_SECTION mWaitersCountLock; /* Serialize access to mWaitersCount. */ 00244 } cnd_t; 00245 #else 00246 typedef pthread_cond_t cnd_t; 00247 #endif 00248 00254 int cnd_init(cnd_t *cond); 00255 00259 void cnd_destroy(cnd_t *cond); 00260 00269 int cnd_signal(cnd_t *cond); 00270 00279 int cnd_broadcast(cnd_t *cond); 00280 00291 int cnd_wait(cnd_t *cond, mtx_t *mtx); 00292 00305 int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts); 00306 00307 /* Thread */ 00308 #if defined(_TTHREAD_WIN32_) 00309 typedef HANDLE thrd_t; 00310 #else 00311 typedef pthread_t thrd_t; 00312 #endif 00313 00322 typedef int (*thrd_start_t)(void *arg); 00323 00336 int thrd_create(thrd_t *thr, thrd_start_t func, void *arg); 00337 00341 thrd_t thrd_current(void); 00342 00345 int thrd_detach(thrd_t thr); 00346 00352 int thrd_equal(thrd_t thr0, thrd_t thr1); 00353 00357 void thrd_exit(int res); 00358 00368 int thrd_join(thrd_t thr, int *res); 00369 00380 int thrd_sleep(const struct timespec *time_point, struct timespec *remaining); 00381 00386 void thrd_yield(void); 00387 00388 /* Thread local storage */ 00389 #if defined(_TTHREAD_WIN32_) 00390 typedef DWORD tss_t; 00391 #else 00392 typedef pthread_key_t tss_t; 00393 #endif 00394 00398 typedef void (*tss_dtor_t)(void *val); 00399 00410 int tss_create(tss_t *key, tss_dtor_t dtor); 00411 00417 void tss_delete(tss_t key); 00418 00424 void *tss_get(tss_t key); 00425 00433 int tss_set(tss_t key, void *val); 00434 00435 00436 #endif /* _TINYTHREAD_H_ */ 00437