TinyCThread  1.1
tinycthread.h
Go to the documentation of this file.
1 /* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; -*-
2 Copyright (c) 2012 Marcus Geelnard
3 Copyright (c) 2013-2014 Evan Nemerson
4 
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8 
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17 
18  2. Altered source versions must be plainly marked as such, and must not be
19  misrepresented as being the original software.
20 
21  3. This notice may not be removed or altered from any source
22  distribution.
23 */
24 
25 #ifndef _TINYCTHREAD_H_
26 #define _TINYCTHREAD_H_
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
55 /* Which platform are we on? */
56 #if !defined(_TTHREAD_PLATFORM_DEFINED_)
57  #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
58  #define _TTHREAD_WIN32_
59  #else
60  #define _TTHREAD_POSIX_
61  #endif
62  #define _TTHREAD_PLATFORM_DEFINED_
63 #endif
64 
65 /* Activate some POSIX functionality (e.g. clock_gettime and recursive mutexes) */
66 #if defined(_TTHREAD_POSIX_)
67  #undef _FEATURES_H
68  #if !defined(_GNU_SOURCE)
69  #define _GNU_SOURCE
70  #endif
71  #if !defined(_POSIX_C_SOURCE) || ((_POSIX_C_SOURCE - 0) < 199309L)
72  #undef _POSIX_C_SOURCE
73  #define _POSIX_C_SOURCE 199309L
74  #endif
75  #if !defined(_XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 500)
76  #undef _XOPEN_SOURCE
77  #define _XOPEN_SOURCE 500
78  #endif
79 #endif
80 
81 /* Generic includes */
82 #include <time.h>
83 
84 /* Platform specific includes */
85 #if defined(_TTHREAD_POSIX_)
86  #include <pthread.h>
87 #elif defined(_TTHREAD_WIN32_)
88  #ifndef WIN32_LEAN_AND_MEAN
89  #define WIN32_LEAN_AND_MEAN
90  #define __UNDEF_LEAN_AND_MEAN
91  #endif
92  #include <windows.h>
93  #ifdef __UNDEF_LEAN_AND_MEAN
94  #undef WIN32_LEAN_AND_MEAN
95  #undef __UNDEF_LEAN_AND_MEAN
96  #endif
97 #endif
98 
99 /* Compiler-specific information */
100 #if defined(__GNUC__)
101  #define TTHREAD_NORETURN __attribute__((noreturn))
102 #else
103  #define TTHREAD_NORETURN
104 #endif
105 
106 /* If TIME_UTC is missing, provide it and provide a wrapper for
107  timespec_get. */
108 #ifndef TIME_UTC
109 #define TIME_UTC 1
110 #define _TTHREAD_EMULATE_TIMESPEC_GET_
111 
112 #if defined(_TTHREAD_WIN32_)
113 struct _tthread_timespec {
114  time_t tv_sec;
115  long tv_nsec;
116 };
117 #define timespec _tthread_timespec
118 #endif
119 
120 int _tthread_timespec_get(struct timespec *ts, int base);
121 #define timespec_get _tthread_timespec_get
122 #endif
123 
125 #define TINYCTHREAD_VERSION_MAJOR 1
126 
127 #define TINYCTHREAD_VERSION_MINOR 2
128 
129 #define TINYCTHREAD_VERSION (TINYCTHREAD_VERSION_MAJOR * 100 + TINYCTHREAD_VERSION_MINOR)
130 
150 /* FIXME: Check for a PROPER value of __STDC_VERSION__ to know if we have C11 */
151 #if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) && !defined(_Thread_local)
152  #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
153  #define _Thread_local __thread
154  #else
155  #define _Thread_local __declspec(thread)
156  #endif
157 #endif
158 
159 /* Macros */
160 #if defined(_TTHREAD_WIN32_)
161 #define TSS_DTOR_ITERATIONS (4)
162 #else
163 #define TSS_DTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS
164 #endif
165 
166 /* Function return values */
167 #define thrd_error 0
168 #define thrd_success 1
169 #define thrd_timedout 2
170 #define thrd_busy 3
171 #define thrd_nomem 4
173 /* Mutex types */
174 #define mtx_plain 0
175 #define mtx_timed 1
176 #define mtx_recursive 2
177 
178 /* Mutex */
179 #if defined(_TTHREAD_WIN32_)
180 typedef struct {
181  union {
182  CRITICAL_SECTION cs; /* Critical section handle (used for non-timed mutexes) */
183  HANDLE mut; /* Mutex handle (used for timed mutex) */
184  } mHandle; /* Mutex handle */
185  int mAlreadyLocked; /* TRUE if the mutex is already locked */
186  int mRecursive; /* TRUE if the mutex is recursive */
187  int mTimed; /* TRUE if the mutex is timed */
188 } mtx_t;
189 #else
190 typedef pthread_mutex_t mtx_t;
191 #endif
192 
205 int mtx_init(mtx_t *mtx, int type);
206 
210 void mtx_destroy(mtx_t *mtx);
211 
220 int mtx_lock(mtx_t *mtx);
221 
224 int mtx_timedlock(mtx_t *mtx, const struct timespec *ts);
225 
234 int mtx_trylock(mtx_t *mtx);
235 
241 int mtx_unlock(mtx_t *mtx);
242 
243 /* Condition variable */
244 #if defined(_TTHREAD_WIN32_)
245 typedef struct {
246  HANDLE mEvents[2]; /* Signal and broadcast event HANDLEs. */
247  unsigned int mWaitersCount; /* Count of the number of waiters. */
248  CRITICAL_SECTION mWaitersCountLock; /* Serialize access to mWaitersCount. */
249 } cnd_t;
250 #else
251 typedef pthread_cond_t cnd_t;
252 #endif
253 
259 int cnd_init(cnd_t *cond);
260 
264 void cnd_destroy(cnd_t *cond);
265 
274 int cnd_signal(cnd_t *cond);
275 
284 int cnd_broadcast(cnd_t *cond);
285 
296 int cnd_wait(cnd_t *cond, mtx_t *mtx);
297 
310 int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts);
311 
312 /* Thread */
313 #if defined(_TTHREAD_WIN32_)
314 typedef HANDLE thrd_t;
315 #else
316 typedef pthread_t thrd_t;
317 #endif
318 
327 typedef int (*thrd_start_t)(void *arg);
328 
341 int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
342 
346 thrd_t thrd_current(void);
347 
351 int thrd_detach(thrd_t thr);
352 
358 int thrd_equal(thrd_t thr0, thrd_t thr1);
359 
363 void thrd_exit(int res) TTHREAD_NORETURN;
364 
374 int thrd_join(thrd_t thr, int *res);
375 
387 int thrd_sleep(const struct timespec *duration, struct timespec *remaining);
388 
393 void thrd_yield(void);
394 
395 /* Thread local storage */
396 #if defined(_TTHREAD_WIN32_)
397 typedef DWORD tss_t;
398 #else
399 typedef pthread_key_t tss_t;
400 #endif
401 
405 typedef void (*tss_dtor_t)(void *val);
406 
419 int tss_create(tss_t *key, tss_dtor_t dtor);
420 
426 void tss_delete(tss_t key);
427 
433 void *tss_get(tss_t key);
434 
442 int tss_set(tss_t key, void *val);
443 
444 #if defined(_TTHREAD_WIN32_)
445  typedef struct {
446  LONG volatile status;
447  CRITICAL_SECTION lock;
448  } once_flag;
449  #define ONCE_FLAG_INIT {0,}
450 #else
451  #define once_flag pthread_once_t
452  #define ONCE_FLAG_INIT PTHREAD_ONCE_INIT
453 #endif
454 
460 #if defined(_TTHREAD_WIN32_)
461  void call_once(once_flag *flag, void (*func)(void));
462 #else
463  #define call_once(flag,func) pthread_once(flag,func)
464 #endif
465 
466 #ifdef __cplusplus
467 }
468 #endif
469 
470 #endif /* _TINYTHREAD_H_ */
471 
int(* thrd_start_t)(void *arg)
Thread start function.
Definition: tinycthread.h:327
int mtx_trylock(mtx_t *mtx)
Try to lock the given mutex.
thrd_t thrd_current(void)
Identify the calling thread.
int mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
NOT YET IMPLEMENTED.
int mtx_unlock(mtx_t *mtx)
Unlock the given mutex.
int tss_set(tss_t key, void *val)
Set the value for a thread-specific storage.
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
Create a new thread.
void thrd_yield(void)
Yield execution to another thread.
int mtx_init(mtx_t *mtx, int type)
Create a mutex object.
int cnd_init(cnd_t *cond)
Create a condition variable object.
void thrd_exit(int res) TTHREAD_NORETURN
Terminate execution of the calling thread.
int cnd_broadcast(cnd_t *cond)
Broadcast a condition variable.
void mtx_destroy(mtx_t *mtx)
Release any resources used by the given mutex.
int thrd_sleep(const struct timespec *duration, struct timespec *remaining)
Put the calling thread to sleep.
void * tss_get(tss_t key)
Get the value for a thread-specific storage.
#define call_once(flag, func)
Invoke a callback exactly once.
Definition: tinycthread.h:463
int cnd_wait(cnd_t *cond, mtx_t *mtx)
Wait for a condition variable to become signaled.
int cnd_signal(cnd_t *cond)
Signal a condition variable.
int tss_create(tss_t *key, tss_dtor_t dtor)
Create a thread-specific storage.
int mtx_lock(mtx_t *mtx)
Lock the given mutex.
int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
Wait for a condition variable to become signaled.
int thrd_join(thrd_t thr, int *res)
Wait for a thread to terminate.
void tss_delete(tss_t key)
Delete a thread-specific storage.
int thrd_detach(thrd_t thr)
Dispose of any resources allocated to the thread when that thread exits.
void cnd_destroy(cnd_t *cond)
Release any resources used by the given condition variable.
void(* tss_dtor_t)(void *val)
Destructor function for a thread-specific storage.
Definition: tinycthread.h:405
int thrd_equal(thrd_t thr0, thrd_t thr1)
Compare two thread identifiers.