P99
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
p99_tss.h
Go to the documentation of this file.
00001 /* This may look like nonsense, but it really is -*- mode: C -*-             */
00002 /*                                                                           */
00003 /* Except of parts copied from previous work and as explicitly stated below, */
00004 /* the author and copyright holder for this work is                          */
00005 /* (C) copyright  2012 Jens Gustedt, INRIA, France                           */
00006 /*                                                                           */
00007 /* This file is free software; it is part of the P99 project.                */
00008 /* You can redistribute it and/or modify it under the terms of the QPL as    */
00009 /* given in the file LICENSE. It is distributed without any warranty;        */
00010 /* without even the implied warranty of merchantability or fitness for a     */
00011 /* particular purpose.                                                       */
00012 /*                                                                           */
00013 #ifndef P99_TSS_H
00014 #define P99_TSS_H 1
00015 
00016 #define _XOPEN_SOURCE 600
00017 #include <unistd.h>
00018 #include <sys/time.h>
00019 #include <time.h>
00020 #include <pthread.h>
00021 #if defined(__GNUC__) || defined(P00_DOXYGEN)
00022 # include "p99_atomic.h"
00023 #endif
00024 
00025 #include "p99_compiler.h"
00026 
00051 #ifndef PTHREAD_DESTRUCTOR_ITERATIONS
00052 # warning "definition of PTHREAD_DESTRUCTOR_ITERATIONS is missing"
00053 
00059 # define TSS_DTOR_ITERATIONS 1
00060 #else
00061 # define TSS_DTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS
00062 #endif
00063 
00083 P99_ENC_DECLARE(pthread_key_t, tss_t);
00084 
00091 typedef void (*tss_dtor_t)(void*);
00092 
00105 enum thrd_status {
00109   thrd_timedout = ETIMEDOUT,
00113   thrd_success = 0,
00119   thrd_busy = EBUSY,
00123   thrd_error = INT_MIN,
00128   thrd_nomem = ENOMEM,
00133   thrd_intr = -1
00134 };
00135 
00150 p99_inline
00151 int tss_create(tss_t *p00_key, tss_dtor_t dtor) {
00152   return pthread_key_create(&P99_ENCP(p00_key), dtor) ? thrd_error : thrd_success;
00153 }
00154 
00158 p99_inline
00159 void tss_delete(tss_t p00_key) {
00160   (void)pthread_key_delete(P99_ENC(p00_key));
00161 }
00162 
00169 p99_inline
00170 void *tss_get(tss_t p00_key) {
00171   return pthread_getspecific(P99_ENC(p00_key));
00172 }
00173 
00179 p99_inline
00180 int tss_set(tss_t p00_key, void *p00_val) {
00181   return pthread_setspecific(P99_ENC(p00_key), p00_val) ? thrd_error : thrd_success;
00182 }
00183 
00209 struct p99_tss {
00210   tss_t p00_val;
00211   tss_dtor_t p00_func;
00212   bool volatile p00_done;
00213   atomic_flag p00_flg;
00214 };
00215 
00216 typedef struct p99_tss p99_tss;
00217 
00218 /* This is an implementation to bootstrap the thread specific
00219    code. Once initialization functionalities that are better suited
00220    for application code are defined elsewhere. */
00221 p99_inline
00222 void p00_key_once_init(p99_tss * p00_key) {
00223   if (!p00_key->p00_done) {
00224     P99_SPIN_EXCLUDE(&p00_key->p00_flg) {
00225       if (!p00_key->p00_done) {
00226         if (!p00_key->p00_func) p00_key->p00_func = free;
00227         int p00_ret = tss_create(&P99_ENCP(p00_key), p00_key->p00_func);
00228         if (p00_ret) {
00229           errno = p00_ret;
00230           perror("can't create thread specific key");
00231           abort();
00232         }
00233         p00_key->p00_done = true;
00234       }
00235     }
00236   }
00237 }
00238 
00239 p99_inline
00240 void* p00_thread_local_get(p99_tss * p00_key, size_t p00_size) {
00241   p00_key_once_init(p00_key);
00242   void * p00_ret = tss_get(P99_ENCP(p00_key));
00243   if (P99_UNLIKELY(!p00_ret)) {
00244     p00_ret = calloc(1, p00_size);
00245     tss_set(P99_ENCP(p00_key), p00_ret);
00246   }
00247   return p00_ret;
00248 }
00249 
00250 #if defined(thread_local) && !defined(P99_EMULATE_THREAD_LOCAL) && !defined(P00_DOXYGEN)
00251 
00252 #define P99_DECLARE_THREAD_LOCAL(T, NAME)                      \
00253 P99_WEAK(NAME)                                                 \
00254 thread_local T NAME
00255 
00256 #define P99_THREAD_LOCAL(NAME) (NAME)
00257 
00258 #else
00259 
00269 #define P99_DECLARE_THREAD_LOCAL(T, NAME)                      \
00270             \
00271 P99_WEAK(NAME)                                                 \
00272 p99_tss NAME;                                                  \
00273 typedef T P99_PASTE3(p00_, NAME, _type)
00274 
00284 #define P99_THREAD_LOCAL(NAME) (*(P99_PASTE3(p00_, NAME, _type)*)p00_thread_local_get(&(NAME), sizeof(P99_PASTE3(p00_, NAME, _type))))
00285 
00286 #endif
00287 
00288 
00293 #endif
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines