Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/root/ThreadLocalStorage.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // @(#)root/thread:$Id$
0002 /*
0003  * Copyright (c) 2006-2011 High Performance Computing Center Stuttgart,
0004  *                         University of Stuttgart.  All rights reserved.
0005  * Author: Rainer Keller, HLRS
0006  * Modified: Fons Rademakers, CERN
0007  * Modified: Philippe Canal, FNAL
0008  *
0009  * Thread-local storage (TLS) is not supported on all environments.
0010  * This header file and test-program shows how to abstract away, using either
0011  *   __thread,
0012  *   __declspec(thread),
0013  *   thread_local or
0014  *   Pthread-Keys
0015  * depending on the (configure-set) CPP-variables R__HAS___THREAD,
0016  * R__HAS_DECLSPEC_THREAD or R__HAS_PTHREAD.
0017  *
0018  * Use the macros TTHREAD_TLS_DECLARE, TTHREAD_TLS_INIT, and the
0019  * getters and setters TTHREAD_TLS_GET and TTHREAD_TLS_GET
0020  * to work on the declared variables.
0021  *
0022  * In case of PThread keys, we need to resolve to using keys!
0023  * In order to do so, we need to declare and access
0024  * TLS variables through three macros:
0025  *  - TTHREAD_TLS_DECLARE
0026  *  - TTHREAD_TLS_INIT
0027  *  - TTHREAD_TLS_SET and
0028  *  - TTHREAD_TLS_GET
0029  * We do depend on the following (GCC-)extension:
0030  *  - In case of function-local static functions,
0031  *    we declare a sub-function to create a specific key.
0032  * Unfortunately, we do NOT use the following extensions:
0033  *  - Using typeof, we could get rid of the type-declaration
0034  *    which is used for casting, however typeof is not ANSI C.
0035  *  - We do NOT allow something like
0036  *       func (a, TTHREAD_TLS_SET(int, my_var, 5));
0037  *    as we do not use the gcc-extension of returning macro-values.
0038  *
0039  * C++11 requires the implementation of the thread_local storage.
0040  *
0041  *  For simple type use:
0042  *      TTHREAD_TLS(int) varname;
0043  *
0044  *  For array of simple type use:
0045  *      TTHREAD_TLS_ARRAY(int, arraysize, varname);
0046  *
0047  *  For object use:
0048  *      TTHREAD_TLS_DECL(classname, varname);
0049  *      TTHREAD_TLS_DECL_ARG(classname, varname, arg);
0050  *      TTHREAD_TLS_DECL_ARG2(classname, varname, arg1, arg2);
0051  *
0052  */
0053 
0054 #ifndef ROOT_ThreadLocalStorage
0055 #define ROOT_ThreadLocalStorage
0056 
0057 #include <stddef.h>
0058 
0059 #ifdef __cplusplus
0060 #include "RtypesCore.h"
0061 #endif
0062 
0063 #include <ROOT/RConfig.hxx>
0064 
0065 #include "RConfigure.h"
0066 
0067 #if defined(R__MACOSX)
0068 #  if defined(__clang__) && defined(MAC_OS_X_VERSION_10_7) && (defined(__x86_64__) || defined(__i386__))
0069 #    define R__HAS___THREAD
0070 #  elif !defined(R__HAS_PTHREAD)
0071 #    define R__HAS_PTHREAD
0072 #  endif
0073 #endif
0074 #if defined(R__LINUX) || defined(R__AIX)
0075 #  define R__HAS___THREAD
0076 #endif
0077 #if defined(R__SOLARIS) && !defined(R__HAS_PTHREAD)
0078 #  define R__HAS_PTHREAD
0079 #endif
0080 #if defined(R__WIN32)
0081 #  define R__HAS_DECLSPEC_THREAD
0082 #endif
0083 #if defined(R__FBSD)
0084 #  define R__HAS_PTHREAD
0085 #endif
0086 
0087 #ifdef __cplusplus
0088 
0089 // Note that the order is relevant, more than one of the flag might be
0090 // on at the same time and we want to use 'best' option available.
0091 
0092 #  define TTHREAD_TLS(type) thread_local type
0093 #  define TTHREAD_TLS_ARRAY(type,size,name) thread_local type name[size]
0094 #  define TTHREAD_TLS_PTR(name) &name
0095 
0096 #  define TTHREAD_TLS_DECL(type, name) thread_local type name
0097 #  define TTHREAD_TLS_DECL_ARG(type, name, arg) thread_local type name(arg)
0098 #  define TTHREAD_TLS_DECL_ARG2(type, name, arg1, arg2) thread_local type name(arg1,arg2)
0099 
0100 // Available on all platforms
0101 
0102 
0103 // Neither TTHREAD_TLS_DECL_IMPL and TTHREAD_TLS_INIT
0104 // do not delete the object at the end of the process.
0105 
0106 #define TTHREAD_TLS_DECL_IMPL(type, name, ptr, arg) \
0107    TTHREAD_TLS(type *) ptr = 0; \
0108    if (!ptr) ptr = new type(arg); \
0109    type &name = *ptr;
0110 
0111 #define TTHREAD_TLS_DECL_IMPL2(type, name, ptr, arg1, arg2) \
0112    TTHREAD_TLS(type *) ptr = 0; \
0113    if (!ptr) ptr = new type(arg1,arg2); \
0114    type &name = *ptr;
0115 
0116 #ifndef TTHREAD_TLS_DECL
0117 
0118 #define TTHREAD_TLS_DECL(type, name) \
0119    TTHREAD_TLS_DECL_IMPL(type,name,_R__JOIN_(ptr,__LINE__),)
0120 
0121 #define TTHREAD_TLS_DECL_ARG(type, name, arg) \
0122    TTHREAD_TLS_DECL_IMPL(type,name,_R__JOIN_(ptr,__LINE__),arg)
0123 
0124 #define TTHREAD_TLS_DECL_ARG2(type, name, arg1, arg2) \
0125    TTHREAD_TLS_DECL_IMPL2(type,name,_R__JOIN_(ptr,__LINE__),arg1,arg2)
0126 
0127 #endif
0128 
0129 template <int marker, typename T>
0130 T &TTHREAD_TLS_INIT() {
0131    TTHREAD_TLS(T*) ptr = NULL;
0132    TTHREAD_TLS(Bool_t) isInit(kFALSE);
0133    if (!isInit) {
0134       ptr = new T;
0135       isInit = kTRUE;
0136    }
0137    return *ptr;
0138 }
0139 
0140 template <int marker, typename Array, typename T>
0141 Array &TTHREAD_TLS_INIT_ARRAY() {
0142    TTHREAD_TLS(Array*) ptr = NULL;
0143    TTHREAD_TLS(Bool_t) isInit(kFALSE);
0144    if (!isInit) {
0145       ptr = new Array[sizeof(Array)/sizeof(T)];
0146       isInit = kTRUE;
0147    }
0148    return *ptr;
0149 }
0150 
0151 template <int marker, typename T, typename ArgType>
0152 T &TTHREAD_TLS_INIT(ArgType arg) {
0153    TTHREAD_TLS(T*) ptr = NULL;
0154    TTHREAD_TLS(Bool_t) isInit(kFALSE);
0155    if (!isInit) {
0156       ptr = new T(arg);
0157       isInit = kTRUE;
0158    }
0159    return *ptr;
0160 }
0161 
0162 #else // __cplusplus
0163 
0164 // TODO: Evaluate using thread_local / _Thread_local from C11 instead of
0165 // platform-specific solutions such as __thread, __declspec(thread) or the
0166 // pthreads API functions.
0167 
0168 #if defined(R__HAS___THREAD)
0169 
0170 #  define TTHREAD_TLS_DECLARE(type,name)
0171 #  define TTHREAD_TLS_INIT(type,name,value) static __thread type name = (value)
0172 #  define TTHREAD_TLS_SET(type,name,value)  name = (value)
0173 #  define TTHREAD_TLS_GET(type,name)        (name)
0174 #  define TTHREAD_TLS_FREE(name)
0175 
0176 #elif defined(R__HAS_DECLSPEC_THREAD)
0177 
0178 #  define TTHREAD_TLS_DECLARE(type,name)
0179 #  define TTHREAD_TLS_INIT(type,name,value) static __declspec(thread) type name = (value)
0180 #  define TTHREAD_TLS_SET(type,name,value)  name = (value)
0181 #  define TTHREAD_TLS_GET(type,name)        (name)
0182 #  define TTHREAD_TLS_FREE(name)
0183 
0184 #elif defined(R__HAS_PTHREAD)
0185 
0186 #include <assert.h>
0187 #include <pthread.h>
0188 
0189 #  define TTHREAD_TLS_DECLARE(type,name)                                     \
0190    static pthread_key_t _##name##_key;                                       \
0191    static void _##name##_key_delete(void * arg)                              \
0192    {                                                                         \
0193      assert (NULL != arg);                                                   \
0194      free(arg);                                                              \
0195    }                                                                         \
0196    static void _##name##_key_create(void)                                    \
0197    {                                                                         \
0198      int _ret;                                                               \
0199      _ret = pthread_key_create(&(_##name##_key), _##name##_key_delete);      \
0200      _ret = _ret; /* To get rid of warnings in case of NDEBUG */             \
0201      assert (0 == _ret);                                                     \
0202    }                                                                         \
0203    static pthread_once_t _##name##_once = PTHREAD_ONCE_INIT;
0204 
0205 #  define TTHREAD_TLS_INIT(type,name,value)                                  \
0206    do {                                                                      \
0207      void *_ptr;                                                             \
0208      (void) pthread_once(&(_##name##_once), _##name##_key_create);           \
0209      if ((_ptr = pthread_getspecific(_##name##_key)) == NULL) {              \
0210        _ptr = malloc(sizeof(type));                                          \
0211        assert (NULL != _ptr);                                                \
0212        (void) pthread_setspecific(_##name##_key, _ptr);                      \
0213        *((type*)_ptr) = (value);                                             \
0214      }                                                                       \
0215    } while (0)
0216 
0217 #  define TTHREAD_TLS_SET(type,name,value)                                   \
0218    do {                                                                      \
0219      void *_ptr = pthread_getspecific(_##name##_key);                        \
0220      assert (NULL != _ptr);                                                  \
0221      *((type*)_ptr) = (value);                                               \
0222    } while (0)
0223 
0224 #  define TTHREAD_TLS_GET(type,name)                                         \
0225      *((type*)pthread_getspecific(_##name##_key))
0226 
0227 #  define TTHREAD_TLS_FREE(name)                                             \
0228      pthread_key_delete(_##name##_key);
0229 
0230 #else
0231 
0232 #error "No Thread Local Storage (TLS) technology for this platform specified."
0233 
0234 #endif
0235 
0236 #endif // __cplusplus
0237 
0238 #endif
0239