ROOT  6.06/09
Reference Guide
ThreadLocalStorage.h
Go to the documentation of this file.
1 // @(#)root/thread:$Id$
2 /*
3  * Copyright (c) 2006-2011 High Performance Computing Center Stuttgart,
4  * University of Stuttgart. All rights reserved.
5  * Author: Rainer Keller, HLRS
6  * Modified: Fons Rademakers, CERN
7  * Modified: Philippe Canal, FNAL
8  *
9  * Thread-local storage (TLS) is not supported on all environments.
10  * This header file and test-program shows how to abstract away, using either
11  * __thread,
12  * __declspec(thread),
13  * thread_local or
14  * Pthread-Keys
15  * depending on the (configure-set) CPP-variables R__HAS___THREAD,
16  * R__HAS_DECLSPEC_THREAD, R__HAS_THREAD_LOCAL or R__HAS_PTHREAD.
17  *
18  * Use the macros TTHREAD_TLS_DECLARE, TTHREAD_TLS_INIT, and the
19  * getters and setters TTHREAD_TLS_GET and TTHREAD_TLS_GET
20  * to work on the declared variables.
21  *
22  * In case of PThread keys, we need to resolve to using keys!
23  * In order to do so, we need to declare and access
24  * TLS variables through three macros:
25  * - TTHREAD_TLS_DECLARE
26  * - TTHREAD_TLS_INIT
27  * - TTHREAD_TLS_SET and
28  * - TTHREAD_TLS_GET
29  * We do depend on the following (GCC-)extension:
30  * - In case of function-local static functions,
31  * we declare a sub-function to create a specific key.
32  * Unfortunately, we do NOT use the following extensions:
33  * - Using typeof, we could get rid of the type-declaration
34  * which is used for casting, however typeof is not ANSI C.
35  * - We do NOT allow something like
36  * func (a, TTHREAD_TLS_SET(int, my_var, 5));
37  * as we do not use the gcc-extension of returning macro-values.
38  *
39  * C++11 requires the implementation of the thread_local storage but
40  * a few platforms do not yet implement it.
41  *
42  * For simple type use:
43  * TTHREAD_TLS(int) varname;
44  *
45  * For array of simple type use:
46  * TTHREAD_TLS_ARRAY(int, arraysize, varname);
47  *
48  * For object use:
49  * TTHREAD_TLS_DECL(classname, varname);
50  * TTHREAD_TLS_DECL_ARG(classname, varname, arg);
51  * TTHREAD_TLS_DECL_ARG2(classname, varname, arg1, arg2);
52  *
53  */
54 
55 #ifndef ROOT_ThreadLocalStorage
56 #define ROOT_ThreadLocalStorage
57 
58 #ifndef ROOT_RConfig
59 #include "RConfig.h"
60 #endif
61 
62 #ifndef ROOT_RConfigure
63 #include "RConfigure.h"
64 #endif
65 
66 #if defined(R__MACOSX)
67 # if defined(__clang__) && defined(MAC_OS_X_VERSION_10_7) && (defined(__x86_64__) || defined(__i386__))
68 # define R__HAS___THREAD
69 # elif !defined(R__HAS_PTHREAD)
70 # define R__HAS_PTHREAD
71 # endif
72 #endif
73 #if defined(R__LINUX) || defined(R__AIX)
74 # define R__HAS___THREAD
75 #endif
76 #if defined(R__SOLARIS) && !defined(R__HAS_PTHREAD)
77 # define R__HAS_PTHREAD
78 #endif
79 #if defined(R__WIN32)
80 # define R__HAS_DECLSPEC_THREAD
81 #endif
82 
83 #if __cplusplus >= 201103L
84 
85 // Clang 3.4 also support SD-6 (feature test macros __cpp_*), but no thread local macro
86 # if defined(__clang__)
87 
88 # if __has_feature(cxx_thread_local)
89  // thread_local was added in Clang 3.3
90  // Still requires libstdc++ from GCC 4.8
91  // For that __GLIBCXX__ isn't good enough
92  // Also the MacOS build of clang does *not* support thread local yet.
93 # define R__HAS_THREAD_LOCAL
94 # else
95 # define R__HAS___THREAD
96 # endif
97 
98 # elif defined(__INTEL_COMPILER)
99 # define R__HAS__THREAD
100 
101 # elif defined(__GNUG__) && (__GNUC__ <= 4 && __GNUC_MINOR__ < 8)
102  // The C++11 thread_local keyword is supported in GCC only since 4.8
103 # define R__HAS___THREAD
104 # else
105 # define R__HAS_THREAD_LOCAL
106 # endif
107 
108 #endif
109 
110 
111 #ifdef __cplusplus
112 
113 // Note that the order is relevant, more than one of the flag might be
114 // on at the same time and we want to use 'best' option available.
115 
116 #ifdef __CINT__
117 
118 # define TTHREAD_TLS(type) static type
119 # define TTHREAD_TLS_ARRAY(type,size,name) static type name[size]
120 # define TTHREAD_TLS_PTR(name) &name
121 
122 #elif defined(R__HAS_THREAD_LOCAL)
123 
124 # define TTHREAD_TLS(type) thread_local type
125 # define TTHREAD_TLS_ARRAY(type,size,name) thread_local type name[size]
126 # define TTHREAD_TLS_PTR(name) &name
127 
128 # define TTHREAD_TLS_DECL(type, name) thread_local type name
129 # define TTHREAD_TLS_DECL_ARG(type, name, arg) thread_local type name(arg)
130 # define TTHREAD_TLS_DECL_ARG2(type, name, arg1, arg2) thread_local type name(arg1,arg2)
131 
132 #elif defined(R__HAS___THREAD)
133 
134 # define TTHREAD_TLS(type) static __thread type
135 # define TTHREAD_TLS_ARRAY(type,size,name) static __thread type name[size]
136 # define TTHREAD_TLS_PTR(name) &name
137 
138 #elif defined(R__HAS_DECLSPEC_THREAD)
139 
140 # define TTHREAD_TLS(type) static __declspec(thread) type
141 # define TTHREAD_TLS_ARRAY(type,size,name) static __declspec(thread) type name[size]
142 # define TTHREAD_TLS_PTR(name) &name
143 
144 #elif defined(R__HAS_PTHREAD)
145 
146 #include <assert.h>
147 #include <pthread.h>
148 
149 template <typename type> class TThreadTLSWrapper
150 {
151 private:
152  pthread_key_t fKey;
153  type fInitValue;
154 
155  static void key_delete(void *arg) {
156  assert (NULL != arg);
157  delete (type*)(arg);
158  }
159 
160 public:
161 
162  TThreadTLSWrapper() : fInitValue() {
163 
164  pthread_key_create(&(fKey), key_delete);
165  }
166 
167  TThreadTLSWrapper(const type &value) : fInitValue(value) {
168 
169  pthread_key_create(&(fKey), key_delete);
170  }
171 
172  ~TThreadTLSWrapper() {
173  pthread_key_delete(fKey);
174  }
175 
176  type& get() {
177  void *ptr = pthread_getspecific(fKey);
178  if (!ptr) {
179  ptr = new type(fInitValue);
180  assert (NULL != ptr);
181  (void) pthread_setspecific(fKey, ptr);
182  }
183  return *(type*)ptr;
184  }
185 
186  type& operator=(const type &in) {
187  type &ptr = get();
188  ptr = in;
189  return ptr;
190  }
191 
192  operator type&() {
193  return get();
194  }
195 
196 };
197 
198 template <typename type,int size> class TThreadTLSArrayWrapper
199 {
200 private:
201  pthread_key_t fKey;
202 
203  static void key_delete(void *arg) {
204  assert (NULL != arg);
205  delete [] (type*)(arg);
206  }
207 
208 public:
209 
210  TThreadTLSArrayWrapper() {
211 
212  pthread_key_create(&(fKey), key_delete);
213  }
214 
215  ~TThreadTLSArrayWrapper() {
216  pthread_key_delete(fKey);
217  }
218 
219  type* get() {
220  void *ptr = pthread_getspecific(fKey);
221  if (!ptr) {
222  ptr = new type[size];
223  assert (NULL != ptr);
224  (void) pthread_setspecific(fKey, ptr);
225  }
226  return (type*)ptr;
227  }
228 
229 // type& operator=(const type &in) {
230 // type &ptr = get();
231 // ptr = in;
232 // return ptr;
233 // }
234 //
235  operator type*() {
236  return get();
237  }
238 
239 };
240 
241 # define TTHREAD_TLS(type) static TThreadTLSWrapper<type>
242 # define TTHREAD_TLS_ARRAY(type,size,name) static TThreadTLSArrayWrapper<type,size> name;
243 # define TTHREAD_TLS_PTR(name) &(name.get())
244 # define TTHREAD_TLS_OBJ(index,type,name) type &name( TTHREAD_TLS_INIT<index,type>() )
245 
246 #else
247 
248 #error "No Thread Local Storage (TLS) technology for this platform specified."
249 
250 #endif
251 
252 // Available on all platforms
253 
254 
255 // Neither TTHREAD_TLS_DECL_IMPL and TTHREAD_TLS_INIT
256 // do not delete the object at the end of the process.
257 
258 #define TTHREAD_TLS_DECL_IMPL(type, name, ptr, arg) \
259  TTHREAD_TLS(type *) ptr = 0; \
260  if (!ptr) ptr = new type(arg); \
261  type &name = *ptr;
262 
263 #define TTHREAD_TLS_DECL_IMPL2(type, name, ptr, arg1, arg2) \
264  TTHREAD_TLS(type *) ptr = 0; \
265  if (!ptr) ptr = new type(arg1,arg2); \
266  type &name = *ptr;
267 
268 #ifndef TTHREAD_TLS_DECL
269 
270 #define TTHREAD_TLS_DECL(type, name) \
271  TTHREAD_TLS_DECL_IMPL(type,name,_R__JOIN_(ptr,__LINE__),)
272 
273 #define TTHREAD_TLS_DECL_ARG(type, name, arg) \
274  TTHREAD_TLS_DECL_IMPL(type,name,_R__JOIN_(ptr,__LINE__),arg)
275 
276 #define TTHREAD_TLS_DECL_ARG2(type, name, arg1, arg2) \
277  TTHREAD_TLS_DECL_IMPL2(type,name,_R__JOIN_(ptr,__LINE__),arg1,arg2)
278 
279 #endif
280 
281 template <int marker, typename T>
282 T &TTHREAD_TLS_INIT() {
283  TTHREAD_TLS(T*) ptr = NULL;
284  TTHREAD_TLS(Bool_t) isInit(kFALSE);
285  if (!isInit) {
286  ptr = new T;
287  isInit = kTRUE;
288  }
289  return *ptr;
290 }
291 
292 template <int marker, typename Array, typename T>
293 Array &TTHREAD_TLS_INIT_ARRAY() {
294  TTHREAD_TLS(Array*) ptr = NULL;
295  TTHREAD_TLS(Bool_t) isInit(kFALSE);
296  if (!isInit) {
297  ptr = new Array[sizeof(Array)/sizeof(T)];
298  isInit = kTRUE;
299  }
300  return *ptr;
301 }
302 
303 template <int marker, typename T, typename ArgType>
304 T &TTHREAD_TLS_INIT(ArgType arg) {
305  TTHREAD_TLS(T*) ptr = NULL;
306  TTHREAD_TLS(Bool_t) isInit(kFALSE);
307  if (!isInit) {
308  ptr = new T(arg);
309  isInit = kTRUE;
310  }
311  return *ptr;
312 }
313 
314 #else // __cplusplus
315 
316 #if defined(R__HAS_THREAD_LOCAL)
317 
318 # define TTHREAD_TLS_DECLARE(type,name)
319 # define TTHREAD_TLS_INIT(type,name,value) thread_local type name = (value)
320 # define TTHREAD_TLS_SET(type,name,value) name = (value)
321 # define TTHREAD_TLS_GET(type,name) (name)
322 # define TTHREAD_TLS_FREE(name)
323 
324 #elif defined(R__HAS___THREAD)
325 
326 # define TTHREAD_TLS_DECLARE(type,name)
327 # define TTHREAD_TLS_INIT(type,name,value) static __thread type name = (value)
328 # define TTHREAD_TLS_SET(type,name,value) name = (value)
329 # define TTHREAD_TLS_GET(type,name) (name)
330 # define TTHREAD_TLS_FREE(name)
331 
332 #elif defined(R__HAS_DECLSPEC_THREAD)
333 
334 # define TTHREAD_TLS_DECLARE(type,name)
335 # define TTHREAD_TLS_INIT(type,name,value) static __declspec(thread) type name = (value)
336 # define TTHREAD_TLS_SET(type,name,value) name = (value)
337 # define TTHREAD_TLS_GET(type,name) (name)
338 # define TTHREAD_TLS_FREE(name)
339 
340 #elif defined(R__HAS_PTHREAD)
341 
342 #include <assert.h>
343 #include <pthread.h>
344 
345 # define TTHREAD_TLS_DECLARE(type,name) \
346  static pthread_key_t _##name##_key; \
347  static void _##name##_key_delete(void * arg) \
348  { \
349  assert (NULL != arg); \
350  free(arg); \
351  } \
352  static void _##name##_key_create(void) \
353  { \
354  int _ret; \
355  _ret = pthread_key_create(&(_##name##_key), _##name##_key_delete); \
356  _ret = _ret; /* To get rid of warnings in case of NDEBUG */ \
357  assert (0 == _ret); \
358  } \
359  static pthread_once_t _##name##_once = PTHREAD_ONCE_INIT;
360 
361 # define TTHREAD_TLS_INIT(type,name,value) \
362  do { \
363  void *_ptr; \
364  (void) pthread_once(&(_##name##_once), _##name##_key_create); \
365  if ((_ptr = pthread_getspecific(_##name##_key)) == NULL) { \
366  _ptr = malloc(sizeof(type)); \
367  assert (NULL != _ptr); \
368  (void) pthread_setspecific(_##name##_key, _ptr); \
369  *((type*)_ptr) = (value); \
370  } \
371  } while (0)
372 
373 # define TTHREAD_TLS_SET(type,name,value) \
374  do { \
375  void *_ptr = pthread_getspecific(_##name##_key); \
376  assert (NULL != _ptr); \
377  *((type*)_ptr) = (value); \
378  } while (0)
379 
380 # define TTHREAD_TLS_GET(type,name) \
381  *((type*)pthread_getspecific(_##name##_key))
382 
383 # define TTHREAD_TLS_FREE(name) \
384  pthread_key_delete(_##name##_key);
385 
386 #else
387 
388 #error "No Thread Local Storage (TLS) technology for this platform specified."
389 
390 #endif
391 
392 #endif // __cplusplus
393 
394 #endif
395 
double T(double x)
Definition: ChebyshevPol.h:34
#define assert(cond)
Definition: unittest.h:542
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
if(pyself &&pyself!=Py_None)
const char * Array
int type
Definition: TGX11.cxx:120
Binding & operator=(OUT(*fun)(void))
typedef void((*Func_t)())
#define NULL
Definition: Rtypes.h:82
const Bool_t kTRUE
Definition: Rtypes.h:91