Go to the documentation of this file.
32 #if !p99_has_feature(threads_h)
58 #ifndef PTHREAD_DESTRUCTOR_ITERATIONS
59 # warning "definition of PTHREAD_DESTRUCTOR_ITERATIONS is missing"
66 # define TSS_DTOR_ITERATIONS 1
68 # define TSS_DTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS
167 void tss_delete(
tss_t p00_key) {
178 void *tss_get(
tss_t p00_key) {
179 return pthread_getspecific(
P99_ENC(p00_key));
189 int tss_set(
tss_t p00_key,
void *p00_val) {
239 bool volatile p00_done;
249 atomic_flag_clear_explicit(&p00_el->p00_flg, memory_order_release);
258 void p00_tss_init(
p99_tss * p00_key) {
261 if (!p00_key->p00_done) {
265 perror(
"can't create thread specific key");
268 p00_key->p00_done =
true;
280 void p99_tss_delete(
p99_tss * p00_key) {
281 p00_tss_init(p00_key);
283 memcpy(p00_key, &
P99_LVAL(
p99_tss const, .p00_done =
false),
sizeof *p00_key);
292 void* p99_tss_get(
p99_tss * p00_key) {
293 p00_tss_init(p00_key);
315 int p99_tss_set(
p99_tss * p00_key,
void *p00_val) {
317 void * p00_vol = p99_tss_get(p00_key);
318 if (p00_val != p00_vol) {
319 p00_ret = tss_set(
P99_ENCP(p00_key), p00_val);
330 #define p99_tss_set(...) P99_CALL_DEFARG(p99_tss_set, 2, __VA_ARGS__)
333 #define p99_tss_set_defarg_1() (0)
373 # define P99_TSS_DECLARE_LOCAL(T, NAME, DTOR) \
377 # define P99_TSS_DECLARE_LOCAL(...) \
378 P99_IF_LT(P99_NARG(__VA_ARGS__), 3) \
379 (P00_TSS_DECLARE_LOCAL(__VA_ARGS__, (free))) \
380 (P00_TSS_DECLARE_LOCAL(__VA_ARGS__))
382 #define P00_TSS_DECLARE_LOCAL(T, NAME, DTOR) \
384 P00_TSS_DECLARE_LOCAL3(NAME, T, DTOR); \
385 P00_TSS_DEFINE_LOCAL3(NAME, T, DTOR)
387 # define P99_TSS_DECLARE_LOCAL_EXTERN(...) \
388 P99_IF_LT(P99_NARG(__VA_ARGS__), 3) \
389 (P00_TSS_DECLARE_LOCAL_EXTERN(__VA_ARGS__, (free))) \
390 (P00_TSS_DECLARE_LOCAL_EXTERN(__VA_ARGS__))
392 #define P00_TSS_DECLARE_LOCAL_EXTERN(T, NAME, DTOR) \
394 P00_TSS_DECLARE_LOCAL3(NAME, T, DTOR)
396 # define P99_TSS_DEFINE_LOCAL(...) \
397 P99_IF_LT(P99_NARG(__VA_ARGS__), 3) \
398 (P00_TSS_DEFINE_LOCAL(__VA_ARGS__, (free))) \
399 (P00_TSS_DEFINE_LOCAL(__VA_ARGS__))
401 #define P00_TSS_DEFINE_LOCAL(T, NAME, DTOR) \
402 P00_TSS_DEFINE_LOCAL3(NAME, T, DTOR)
408 #define P00_TSS_DECLARE_LOCAL3(NAME, T, DTOR) \
411 typedef T P99_PASTE3(p00_, NAME, _type)
413 #define P00_TSS_DEFINE_LOCAL3(NAME, T, DTOR) \
414 p99_tss NAME = { .p99_dtor = (DTOR), }
427 #define P99_TSS_LOCAL(NAME) (*(P99_PASTE3(p00_, NAME, _type)*)p99_tss_get_alloc(&(NAME), sizeof(P99_PASTE3(p00_, NAME, _type))))
442 void* p99_tss_get_alloc(
p99_tss * p00_key,
size_t p00_size) {
443 void * p00_ret = p99_tss_get(p00_key);
446 p00_ret =
calloc(1, p00_size);
455 #if defined(thread_local) && !defined(P99_EMULATE_THREAD_LOCAL) && !defined(P00_DOXYGEN)
457 #define P99_DECLARE_THREAD_LOCAL(T, NAME) \
461 #define P99_DECLARE_THREAD_LOCAL_EXTERN(T, NAME) \
465 #define P99_DEFINE_THREAD_LOCAL(T, NAME) \
469 #define P99_THREAD_LOCAL(NAME) (NAME)
485 #define P99_DECLARE_THREAD_LOCAL P99_TSS_DECLARE_LOCAL
487 #define P99_DECLARE_THREAD_LOCAL_EXTERN P99_TSS_DECLARE_LOCAL_EXTERN
489 #define P99_DEFINE_THREAD_LOCAL P99_TSS_DEFINE_LOCAL
499 #define P99_THREAD_LOCAL P99_TSS_LOCAL
@ thrd_timedout
returned by a timed wait function to indicate that the time specified in the call was reached without...
Macros for default arguments to functions.
@ thrd_busy
returned by a function to indicate that the requested operation failed because a resource requested b...
#define P99_TSS_DECLARE_LOCAL(T, NAME, DTOR)
#define P99_WARN_UNUSED_RESULT
On architectures that support this, warn if the result of a function is not used.
#define calloc(...)
Default arguments for C99 function calloc
#define P99_SPIN_EXCLUDE(FLAGP)
Protect the following block or statement as a critical section of the program by using FLAGP as a spi...
#define P99_ENC(OBJ)
Access an encapsulated object.
@ thrd_success
returned by a function to indicate that the requested operation succeeded
#define p99_inline
Try to force a function always to be inlined.
#define P99_PROTOTYPE(...)
Define the prototype of function NAME.
#define P99_DEFARG_DOCU(NAME)
Provide a documentation section to a function defined with P99_CALL_DEFARG.
@ thrd_nomem
returned by a function to indicate that the requested operation failed because it was unable to alloc...
#define P99_LVAL(...)
Define an lvalue of type T, where T is the first parameter in the variable parameter list.
void(* tss_dtor_t)(void *)
which is the function pointer type void (*)(void*), used for a destructor for a thread-specific stora...
#define P99_ENC_DECLARE(T, NAME)
Encapsulate an object of type T in a new type called NAME.
tss_dtor_t p99_dtor
Destructor function that is automatically called at the termination of a thread.
#define pthread_key_create(...)
Default arguments for POSIX function pthread_key_create.
@ thrd_intr
(extension) returned by ::thrd_sleep to indicate that the corresponding request has been interrupted ...
@ thrd_error
returned by a function to indicate that the requested operation failed
#define P99_ENCP(OBJP)
Access an encapsulated object through a pointer.
typedef **addtogroup threads C11 thread emulation on top of POSIX threads ****This is a relatively straightforward implementation of the C11 **thread model on top of POSIX threads The main difficulty this presents **is that the thread entry function signature differs between the **two C11 thread returns an< code > int</code > whereas POSIX returns **a< code > void *</code > ****You can find the thread management interfaces through the **documentation of the type ::thrd_t ****remark In addition to POSIX threads this implementation needs **some C11 atomic operations for initialization via ::call_once and **status communication ****struct tss_t tss_t
#define P99_UNLIKELY(...)
Mark the conditional expression as being unlikely.
p99_tss * p99_tss_init(p99_tss *p00_el, tss_dtor_t p00_f)
thrd_status
C11 thread function return values.
A stub structure to hold a thread local variable if thread_local is not available.