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_ */ |