TinyCThread 1.1
tinycthread.h
Go to the documentation of this file.
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