/simpletypesystem/trunk

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/simpletypesystem/trunk
128 by Gustav Hartvigsson
* Removed blasted #pragma message s from Thread.h
1
/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; -*-
2
Copyright (c) 2012 Marcus Geelnard
151.1.2 by Gustav Hartvigsson
* Removed wchar.
3
Copyright (c) 2013-2016 Evan Nemerson
128 by Gustav Hartvigsson
* Removed blasted #pragma message s from Thread.h
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
32
/**
33
* @file
34
* @mainpage TinyCThread API Reference
35
*
36
* @section intro_sec Introduction
37
* TinyCThread is a minimal, portable implementation of basic threading
38
* classes for C.
39
*
40
* They closely mimic the functionality and naming of the C11 standard, and
41
* should be easily replaceable with the corresponding standard variants.
42
*
43
* @section port_sec Portability
44
* The Win32 variant uses the native Win32 API for implementing the thread
45
* classes, while for other systems, the POSIX threads API (pthread) is used.
46
*
47
* @section misc_sec Miscellaneous
48
* The following special keywords are available: #_Thread_local.
49
*
50
* For more detailed information, browse the different sections of this
51
* documentation. A good place to start is:
52
* tinycthread.h.
53
*/
54
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
151.1.2 by Gustav Hartvigsson
* Removed wchar.
79
  #define _XPG6
128 by Gustav Hartvigsson
* Removed blasted #pragma message s from Thread.h
80
#endif
81
82
/* Generic includes */
83
#include <time.h>
84
85
/* Platform specific includes */
86
#if defined(_TTHREAD_POSIX_)
87
  #include <pthread.h>
88
#elif defined(_TTHREAD_WIN32_)
89
  #ifndef WIN32_LEAN_AND_MEAN
90
    #define WIN32_LEAN_AND_MEAN
91
    #define __UNDEF_LEAN_AND_MEAN
92
  #endif
93
  #include <windows.h>
94
  #ifdef __UNDEF_LEAN_AND_MEAN
95
    #undef WIN32_LEAN_AND_MEAN
96
    #undef __UNDEF_LEAN_AND_MEAN
97
  #endif
98
#endif
99
100
/* Compiler-specific information */
101
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
102
  #define TTHREAD_NORETURN _Noreturn
103
#elif defined(__GNUC__)
104
  #define TTHREAD_NORETURN __attribute__((__noreturn__))
105
#else
106
  #define TTHREAD_NORETURN
107
#endif
108
109
/* If TIME_UTC is missing, provide it and provide a wrapper for
110
   timespec_get. */
111
#ifndef TIME_UTC
112
#define TIME_UTC 1
113
#define _TTHREAD_EMULATE_TIMESPEC_GET_
114
115
#if defined(_TTHREAD_WIN32_)
116
struct _tthread_timespec {
117
  time_t tv_sec;
118
  long   tv_nsec;
119
};
120
#define timespec _tthread_timespec
121
#endif
122
123
int _tthread_timespec_get(struct timespec *ts, int base);
124
#define timespec_get _tthread_timespec_get
125
#endif
126
127
/** TinyCThread version (major number). */
128
#define TINYCTHREAD_VERSION_MAJOR 1
129
/** TinyCThread version (minor number). */
130
#define TINYCTHREAD_VERSION_MINOR 2
131
/** TinyCThread version (full version). */
132
#define TINYCTHREAD_VERSION (TINYCTHREAD_VERSION_MAJOR * 100 + TINYCTHREAD_VERSION_MINOR)
133
134
/**
135
* @def _Thread_local
136
* Thread local storage keyword.
137
* A variable that is declared with the @c _Thread_local keyword makes the
138
* value of the variable local to each thread (known as thread-local storage,
139
* or TLS). Example usage:
140
* @code
141
* // This variable is local to each thread.
142
* _Thread_local int variable;
143
* @endcode
144
* @note The @c _Thread_local keyword is a macro that maps to the corresponding
145
* compiler directive (e.g. @c __declspec(thread)).
146
* @note This directive is currently not supported on Mac OS X (it will give
147
* a compiler error), since compile-time TLS is not supported in the Mac OS X
148
* executable format. Also, some older versions of MinGW (before GCC 4.x) do
149
* not support this directive, nor does the Tiny C Compiler.
150
* @hideinitializer
151
*/
152
153
#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) && !defined(_Thread_local)
154
 #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
155
  #define _Thread_local __thread
156
 #else
157
  #define _Thread_local __declspec(thread)
158
 #endif
159
#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && (((__GNUC__ << 8) | __GNUC_MINOR__) < ((4 << 8) | 9))
160
 #define _Thread_local __thread
161
#endif
162
163
/* Macros */
164
#if defined(_TTHREAD_WIN32_)
165
#define TSS_DTOR_ITERATIONS (4)
166
#else
167
#define TSS_DTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS
168
#endif
169
170
/* Function return values */
171
#define thrd_error    0 /**< The requested operation failed */
172
#define thrd_success  1 /**< The requested operation succeeded */
173
#define thrd_timedout 2 /**< The time specified in the call was reached without acquiring the requested resource */
174
#define thrd_busy     3 /**< The requested operation failed because a tesource requested by a test and return function is already in use */
175
#define thrd_nomem    4 /**< The requested operation failed because it was unable to allocate memory */
176
177
/* Mutex types */
178
#define mtx_plain     0
179
#define mtx_timed     1
180
#define mtx_recursive 2
181
182
/* Mutex */
183
#if defined(_TTHREAD_WIN32_)
184
typedef struct {
185
  union {
186
    CRITICAL_SECTION cs;      /* Critical section handle (used for non-timed mutexes) */
187
    HANDLE mut;               /* Mutex handle (used for timed mutex) */
188
  } mHandle;                  /* Mutex handle */
189
  int mAlreadyLocked;         /* TRUE if the mutex is already locked */
190
  int mRecursive;             /* TRUE if the mutex is recursive */
191
  int mTimed;                 /* TRUE if the mutex is timed */
192
} mtx_t;
193
#else
194
typedef pthread_mutex_t mtx_t;
195
#endif
196
197
/** Create a mutex object.
198
* @param mtx A mutex object.
199
* @param type Bit-mask that must have one of the following six values:
200
*   @li @c mtx_plain for a simple non-recursive mutex
201
*   @li @c mtx_timed for a non-recursive mutex that supports timeout
202
*   @li @c mtx_plain | @c mtx_recursive (same as @c mtx_plain, but recursive)
203
*   @li @c mtx_timed | @c mtx_recursive (same as @c mtx_timed, but recursive)
204
* @return @ref thrd_success on success, or @ref thrd_error if the request could
205
* not be honored.
206
*/
207
int mtx_init(mtx_t *mtx, int type);
208
209
/** Release any resources used by the given mutex.
210
* @param mtx A mutex object.
211
*/
212
void mtx_destroy(mtx_t *mtx);
213
214
/** Lock the given mutex.
215
* Blocks until the given mutex can be locked. If the mutex is non-recursive, and
216
* the calling thread already has a lock on the mutex, this call will block
217
* forever.
218
* @param mtx A mutex object.
219
* @return @ref thrd_success on success, or @ref thrd_error if the request could
220
* not be honored.
221
*/
222
int mtx_lock(mtx_t *mtx);
223
151.1.2 by Gustav Hartvigsson
* Removed wchar.
224
/** Lock the given mutex, or block until a specific point in time.
225
* Blocks until either the given mutex can be locked, or the specified TIME_UTC
226
* based time.
227
* @param mtx A mutex object.
228
* @param ts A UTC based calendar time
229
* @return @ref The mtx_timedlock function returns thrd_success on success, or
230
* thrd_timedout if the time specified was reached without acquiring the
231
* requested resource, or thrd_error if the request could not be honored.
128 by Gustav Hartvigsson
* Removed blasted #pragma message s from Thread.h
232
*/
233
int mtx_timedlock(mtx_t *mtx, const struct timespec *ts);
234
235
/** Try to lock the given mutex.
236
* The specified mutex shall support either test and return or timeout. If the
237
* mutex is already locked, the function returns without blocking.
238
* @param mtx A mutex object.
239
* @return @ref thrd_success on success, or @ref thrd_busy if the resource
240
* requested is already in use, or @ref thrd_error if the request could not be
241
* honored.
242
*/
243
int mtx_trylock(mtx_t *mtx);
244
245
/** Unlock the given mutex.
246
* @param mtx A mutex object.
247
* @return @ref thrd_success on success, or @ref thrd_error if the request could
248
* not be honored.
249
*/
250
int mtx_unlock(mtx_t *mtx);
251
252
/* Condition variable */
253
#if defined(_TTHREAD_WIN32_)
254
typedef struct {
255
  HANDLE mEvents[2];                  /* Signal and broadcast event HANDLEs. */
256
  unsigned int mWaitersCount;         /* Count of the number of waiters. */
257
  CRITICAL_SECTION mWaitersCountLock; /* Serialize access to mWaitersCount. */
258
} cnd_t;
259
#else
260
typedef pthread_cond_t cnd_t;
261
#endif
262
263
/** Create a condition variable object.
264
* @param cond A condition variable object.
265
* @return @ref thrd_success on success, or @ref thrd_error if the request could
266
* not be honored.
267
*/
268
int cnd_init(cnd_t *cond);
269
270
/** Release any resources used by the given condition variable.
271
* @param cond A condition variable object.
272
*/
273
void cnd_destroy(cnd_t *cond);
274
275
/** Signal a condition variable.
276
* Unblocks one of the threads that are blocked on the given condition variable
277
* at the time of the call. If no threads are blocked on the condition variable
278
* at the time of the call, the function does nothing and return success.
279
* @param cond A condition variable object.
280
* @return @ref thrd_success on success, or @ref thrd_error if the request could
281
* not be honored.
282
*/
283
int cnd_signal(cnd_t *cond);
284
285
/** Broadcast a condition variable.
286
* Unblocks all of the threads that are blocked on the given condition variable
287
* at the time of the call. If no threads are blocked on the condition variable
288
* at the time of the call, the function does nothing and return success.
289
* @param cond A condition variable object.
290
* @return @ref thrd_success on success, or @ref thrd_error if the request could
291
* not be honored.
292
*/
293
int cnd_broadcast(cnd_t *cond);
294
295
/** Wait for a condition variable to become signaled.
296
* The function atomically unlocks the given mutex and endeavors to block until
297
* the given condition variable is signaled by a call to cnd_signal or to
298
* cnd_broadcast. When the calling thread becomes unblocked it locks the mutex
299
* before it returns.
300
* @param cond A condition variable object.
301
* @param mtx A mutex object.
302
* @return @ref thrd_success on success, or @ref thrd_error if the request could
303
* not be honored.
304
*/
305
int cnd_wait(cnd_t *cond, mtx_t *mtx);
306
307
/** Wait for a condition variable to become signaled.
308
* The function atomically unlocks the given mutex and endeavors to block until
309
* the given condition variable is signaled by a call to cnd_signal or to
310
* cnd_broadcast, or until after the specified time. When the calling thread
311
* becomes unblocked it locks the mutex before it returns.
312
* @param cond A condition variable object.
313
* @param mtx A mutex object.
314
* @param xt A point in time at which the request will time out (absolute time).
315
* @return @ref thrd_success upon success, or @ref thrd_timeout if the time
316
* specified in the call was reached without acquiring the requested resource, or
317
* @ref thrd_error if the request could not be honored.
318
*/
319
int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts);
320
321
/* Thread */
322
#if defined(_TTHREAD_WIN32_)
323
typedef HANDLE thrd_t;
324
#else
325
typedef pthread_t thrd_t;
326
#endif
327
328
/** Thread start function.
329
* Any thread that is started with the @ref thrd_create() function must be
330
* started through a function of this type.
331
* @param arg The thread argument (the @c arg argument of the corresponding
332
*        @ref thrd_create() call).
333
* @return The thread return value, which can be obtained by another thread
334
* by using the @ref thrd_join() function.
335
*/
336
typedef int (*thrd_start_t)(void *arg);
337
338
/** Create a new thread.
339
* @param thr Identifier of the newly created thread.
340
* @param func A function pointer to the function that will be executed in
341
*        the new thread.
342
* @param arg An argument to the thread function.
343
* @return @ref thrd_success on success, or @ref thrd_nomem if no memory could
344
* be allocated for the thread requested, or @ref thrd_error if the request
345
* could not be honored.
346
* @note A thread’s identifier may be reused for a different thread once the
347
* original thread has exited and either been detached or joined to another
348
* thread.
349
*/
350
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
351
352
/** Identify the calling thread.
353
* @return The identifier of the calling thread.
354
*/
355
thrd_t thrd_current(void);
356
357
/** Dispose of any resources allocated to the thread when that thread exits.
358
 * @return thrd_success, or thrd_error on error
359
*/
360
int thrd_detach(thrd_t thr);
361
362
/** Compare two thread identifiers.
363
* The function determines if two thread identifiers refer to the same thread.
364
* @return Zero if the two thread identifiers refer to different threads.
365
* Otherwise a nonzero value is returned.
366
*/
367
int thrd_equal(thrd_t thr0, thrd_t thr1);
368
369
/** Terminate execution of the calling thread.
370
* @param res Result code of the calling thread.
371
*/
372
TTHREAD_NORETURN void thrd_exit(int res);
373
374
/** Wait for a thread to terminate.
375
* The function joins the given thread with the current thread by blocking
376
* until the other thread has terminated.
377
* @param thr The thread to join with.
378
* @param res If this pointer is not NULL, the function will store the result
379
*        code of the given thread in the integer pointed to by @c res.
380
* @return @ref thrd_success on success, or @ref thrd_error if the request could
381
* not be honored.
382
*/
383
int thrd_join(thrd_t thr, int *res);
384
385
/** Put the calling thread to sleep.
386
* Suspend execution of the calling thread.
387
* @param duration  Interval to sleep for
388
* @param remaining If non-NULL, this parameter will hold the remaining
389
*                  time until time_point upon return. This will
390
*                  typically be zero, but if the thread was woken up
391
*                  by a signal that is not ignored before duration was
392
*                  reached @c remaining will hold a positive time.
393
* @return 0 (zero) on successful sleep, -1 if an interrupt occurred,
394
*         or a negative value if the operation fails.
395
*/
396
int thrd_sleep(const struct timespec *duration, struct timespec *remaining);
397
398
/** Yield execution to another thread.
399
* Permit other threads to run, even if the current thread would ordinarily
400
* continue to run.
401
*/
402
void thrd_yield(void);
403
404
/* Thread local storage */
405
#if defined(_TTHREAD_WIN32_)
406
typedef DWORD tss_t;
407
#else
408
typedef pthread_key_t tss_t;
409
#endif
410
411
/** Destructor function for a thread-specific storage.
412
* @param val The value of the destructed thread-specific storage.
413
*/
414
typedef void (*tss_dtor_t)(void *val);
415
416
/** Create a thread-specific storage.
417
* @param key The unique key identifier that will be set if the function is
418
*        successful.
419
* @param dtor Destructor function. This can be NULL.
420
* @return @ref thrd_success on success, or @ref thrd_error if the request could
421
* not be honored.
422
* @note On Windows, the @c dtor will definitely be called when
423
* appropriate for threads created with @ref thrd_create.  It will be
424
* called for other threads in most cases, the possible exception being
425
* for DLLs loaded with LoadLibraryEx.  In order to be certain, you
426
* should use @ref thrd_create whenever possible.
427
*/
428
int tss_create(tss_t *key, tss_dtor_t dtor);
429
430
/** Delete a thread-specific storage.
431
* The function releases any resources used by the given thread-specific
432
* storage.
433
* @param key The key that shall be deleted.
434
*/
435
void tss_delete(tss_t key);
436
437
/** Get the value for a thread-specific storage.
438
* @param key The thread-specific storage identifier.
439
* @return The value for the current thread held in the given thread-specific
440
* storage.
441
*/
442
void *tss_get(tss_t key);
443
444
/** Set the value for a thread-specific storage.
445
* @param key The thread-specific storage identifier.
446
* @param val The value of the thread-specific storage to set for the current
447
*        thread.
448
* @return @ref thrd_success on success, or @ref thrd_error if the request could
449
* not be honored.
450
*/
451
int tss_set(tss_t key, void *val);
452
453
#if defined(_TTHREAD_WIN32_)
454
  typedef struct {
455
    LONG volatile status;
456
    CRITICAL_SECTION lock;
457
  } once_flag;
458
  #define ONCE_FLAG_INIT {0,}
459
#else
460
  #define once_flag pthread_once_t
461
  #define ONCE_FLAG_INIT PTHREAD_ONCE_INIT
462
#endif
463
464
/** Invoke a callback exactly once
465
 * @param flag Flag used to ensure the callback is invoked exactly
466
 *        once.
467
 * @param func Callback to invoke.
468
 */
469
#if defined(_TTHREAD_WIN32_)
470
  void call_once(once_flag *flag, void (*func)(void));
471
#else
472
  #define call_once(flag,func) pthread_once(flag,func)
473
#endif
474
475
#ifdef __cplusplus
476
}
477
#endif
478
479
#endif /* _TINYTHREAD_H_ */