Logo ROOT  
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#include <stddef.h>
59
60#ifdef __cplusplus
61#include "RtypesCore.h"
62#endif
63
64#include <ROOT/RConfig.hxx>
65
66#include "RConfigure.h"
67
68#if defined(R__MACOSX)
69# if defined(__clang__) && defined(MAC_OS_X_VERSION_10_7) && (defined(__x86_64__) || defined(__i386__))
70# define R__HAS___THREAD
71# elif !defined(R__HAS_PTHREAD)
72# define R__HAS_PTHREAD
73# endif
74#endif
75#if defined(R__LINUX) || defined(R__AIX)
76# define R__HAS___THREAD
77#endif
78#if defined(R__SOLARIS) && !defined(R__HAS_PTHREAD)
79# define R__HAS_PTHREAD
80#endif
81#if defined(R__WIN32)
82# define R__HAS_DECLSPEC_THREAD
83#endif
84
85#if __cplusplus >= 201103L
86
87// Clang 3.4 also support SD-6 (feature test macros __cpp_*), but no thread local macro
88# if defined(__clang__)
89
90# if __has_feature(cxx_thread_local)
91 // thread_local was added in Clang 3.3
92 // Still requires libstdc++ from GCC 4.8
93 // For that __GLIBCXX__ isn't good enough
94 // Also the MacOS build of clang does *not* support thread local yet.
95# define R__HAS_THREAD_LOCAL
96# else
97# define R__HAS___THREAD
98# endif
99
100# elif defined(__INTEL_COMPILER)
101# define R__HAS__THREAD
102
103# elif defined(__GNUG__) && (__GNUC__ <= 4 && __GNUC_MINOR__ < 8)
104 // The C++11 thread_local keyword is supported in GCC only since 4.8
105# define R__HAS___THREAD
106# else
107# define R__HAS_THREAD_LOCAL
108# endif
109
110#endif
111
112
113#ifdef __cplusplus
114
115// Note that the order is relevant, more than one of the flag might be
116// on at the same time and we want to use 'best' option available.
117
118#ifdef __CINT__
119
120# define TTHREAD_TLS(type) static type
121# define TTHREAD_TLS_ARRAY(type,size,name) static type name[size]
122# define TTHREAD_TLS_PTR(name) &name
123
124#elif defined(R__HAS_THREAD_LOCAL)
125
126# define TTHREAD_TLS(type) thread_local type
127# define TTHREAD_TLS_ARRAY(type,size,name) thread_local type name[size]
128# define TTHREAD_TLS_PTR(name) &name
129
130# define TTHREAD_TLS_DECL(type, name) thread_local type name
131# define TTHREAD_TLS_DECL_ARG(type, name, arg) thread_local type name(arg)
132# define TTHREAD_TLS_DECL_ARG2(type, name, arg1, arg2) thread_local type name(arg1,arg2)
133
134#elif defined(R__HAS___THREAD)
135
136# define TTHREAD_TLS(type) static __thread type
137# define TTHREAD_TLS_ARRAY(type,size,name) static __thread type name[size]
138# define TTHREAD_TLS_PTR(name) &name
139
140#elif defined(R__HAS_DECLSPEC_THREAD)
141
142# define TTHREAD_TLS(type) static __declspec(thread) type
143# define TTHREAD_TLS_ARRAY(type,size,name) static __declspec(thread) type name[size]
144# define TTHREAD_TLS_PTR(name) &name
145
146#elif defined(R__HAS_PTHREAD)
147
148#include <assert.h>
149#include <pthread.h>
150
151template <typename type> class TThreadTLSWrapper
152{
153private:
154 pthread_key_t fKey;
155 type fInitValue;
156
157 static void key_delete(void *arg) {
158 assert (NULL != arg);
159 delete (type*)(arg);
160 }
161
162public:
163
164 TThreadTLSWrapper() : fInitValue() {
165
166 pthread_key_create(&(fKey), key_delete);
167 }
168
169 TThreadTLSWrapper(const type &value) : fInitValue(value) {
170
171 pthread_key_create(&(fKey), key_delete);
172 }
173
174 ~TThreadTLSWrapper() {
175 pthread_key_delete(fKey);
176 }
177
178 type& get() {
179 void *ptr = pthread_getspecific(fKey);
180 if (!ptr) {
181 ptr = new type(fInitValue);
182 assert (NULL != ptr);
183 (void) pthread_setspecific(fKey, ptr);
184 }
185 return *(type*)ptr;
186 }
187
188 type& operator=(const type &in) {
189 type &ptr = get();
190 ptr = in;
191 return ptr;
192 }
193
194 operator type&() {
195 return get();
196 }
197
198};
199
200template <typename type,int size> class TThreadTLSArrayWrapper
201{
202private:
203 pthread_key_t fKey;
204
205 static void key_delete(void *arg) {
206 assert (NULL != arg);
207 delete [] (type*)(arg);
208 }
209
210public:
211
212 TThreadTLSArrayWrapper() {
213
214 pthread_key_create(&(fKey), key_delete);
215 }
216
217 ~TThreadTLSArrayWrapper() {
218 pthread_key_delete(fKey);
219 }
220
221 type* get() {
222 void *ptr = pthread_getspecific(fKey);
223 if (!ptr) {
224 ptr = new type[size];
225 assert (NULL != ptr);
226 (void) pthread_setspecific(fKey, ptr);
227 }
228 return (type*)ptr;
229 }
230
231// type& operator=(const type &in) {
232// type &ptr = get();
233// ptr = in;
234// return ptr;
235// }
236//
237 operator type*() {
238 return get();
239 }
240
241};
242
243# define TTHREAD_TLS(type) static TThreadTLSWrapper<type>
244# define TTHREAD_TLS_ARRAY(type,size,name) static TThreadTLSArrayWrapper<type,size> name;
245# define TTHREAD_TLS_PTR(name) &(name.get())
246# define TTHREAD_TLS_OBJ(index,type,name) type &name( TTHREAD_TLS_INIT<index,type>() )
247
248#else
249
250#error "No Thread Local Storage (TLS) technology for this platform specified."
251
252#endif
253
254// Available on all platforms
255
256
257// Neither TTHREAD_TLS_DECL_IMPL and TTHREAD_TLS_INIT
258// do not delete the object at the end of the process.
259
260#define TTHREAD_TLS_DECL_IMPL(type, name, ptr, arg) \
261 TTHREAD_TLS(type *) ptr = 0; \
262 if (!ptr) ptr = new type(arg); \
263 type &name = *ptr;
264
265#define TTHREAD_TLS_DECL_IMPL2(type, name, ptr, arg1, arg2) \
266 TTHREAD_TLS(type *) ptr = 0; \
267 if (!ptr) ptr = new type(arg1,arg2); \
268 type &name = *ptr;
269
270#ifndef TTHREAD_TLS_DECL
271
272#define TTHREAD_TLS_DECL(type, name) \
273 TTHREAD_TLS_DECL_IMPL(type,name,_R__JOIN_(ptr,__LINE__),)
274
275#define TTHREAD_TLS_DECL_ARG(type, name, arg) \
276 TTHREAD_TLS_DECL_IMPL(type,name,_R__JOIN_(ptr,__LINE__),arg)
277
278#define TTHREAD_TLS_DECL_ARG2(type, name, arg1, arg2) \
279 TTHREAD_TLS_DECL_IMPL2(type,name,_R__JOIN_(ptr,__LINE__),arg1,arg2)
280
281#endif
282
283template <int marker, typename T>
284T &TTHREAD_TLS_INIT() {
285 TTHREAD_TLS(T*) ptr = NULL;
286 TTHREAD_TLS(Bool_t) isInit(kFALSE);
287 if (!isInit) {
288 ptr = new T;
289 isInit = kTRUE;
290 }
291 return *ptr;
292}
293
294template <int marker, typename Array, typename T>
295Array &TTHREAD_TLS_INIT_ARRAY() {
296 TTHREAD_TLS(Array*) ptr = NULL;
297 TTHREAD_TLS(Bool_t) isInit(kFALSE);
298 if (!isInit) {
299 ptr = new Array[sizeof(Array)/sizeof(T)];
300 isInit = kTRUE;
301 }
302 return *ptr;
303}
304
305template <int marker, typename T, typename ArgType>
306T &TTHREAD_TLS_INIT(ArgType arg) {
307 TTHREAD_TLS(T*) ptr = NULL;
308 TTHREAD_TLS(Bool_t) isInit(kFALSE);
309 if (!isInit) {
310 ptr = new T(arg);
311 isInit = kTRUE;
312 }
313 return *ptr;
314}
315
316#else // __cplusplus
317
318#if defined(R__HAS_THREAD_LOCAL)
319
320# define TTHREAD_TLS_DECLARE(type,name)
321# define TTHREAD_TLS_INIT(type,name,value) thread_local type name = (value)
322# define TTHREAD_TLS_SET(type,name,value) name = (value)
323# define TTHREAD_TLS_GET(type,name) (name)
324# define TTHREAD_TLS_FREE(name)
325
326#elif defined(R__HAS___THREAD)
327
328# define TTHREAD_TLS_DECLARE(type,name)
329# define TTHREAD_TLS_INIT(type,name,value) static __thread type name = (value)
330# define TTHREAD_TLS_SET(type,name,value) name = (value)
331# define TTHREAD_TLS_GET(type,name) (name)
332# define TTHREAD_TLS_FREE(name)
333
334#elif defined(R__HAS_DECLSPEC_THREAD)
335
336# define TTHREAD_TLS_DECLARE(type,name)
337# define TTHREAD_TLS_INIT(type,name,value) static __declspec(thread) type name = (value)
338# define TTHREAD_TLS_SET(type,name,value) name = (value)
339# define TTHREAD_TLS_GET(type,name) (name)
340# define TTHREAD_TLS_FREE(name)
341
342#elif defined(R__HAS_PTHREAD)
343
344#include <assert.h>
345#include <pthread.h>
346
347# define TTHREAD_TLS_DECLARE(type,name) \
348 static pthread_key_t _##name##_key; \
349 static void _##name##_key_delete(void * arg) \
350 { \
351 assert (NULL != arg); \
352 free(arg); \
353 } \
354 static void _##name##_key_create(void) \
355 { \
356 int _ret; \
357 _ret = pthread_key_create(&(_##name##_key), _##name##_key_delete); \
358 _ret = _ret; /* To get rid of warnings in case of NDEBUG */ \
359 assert (0 == _ret); \
360 } \
361 static pthread_once_t _##name##_once = PTHREAD_ONCE_INIT;
362
363# define TTHREAD_TLS_INIT(type,name,value) \
364 do { \
365 void *_ptr; \
366 (void) pthread_once(&(_##name##_once), _##name##_key_create); \
367 if ((_ptr = pthread_getspecific(_##name##_key)) == NULL) { \
368 _ptr = malloc(sizeof(type)); \
369 assert (NULL != _ptr); \
370 (void) pthread_setspecific(_##name##_key, _ptr); \
371 *((type*)_ptr) = (value); \
372 } \
373 } while (0)
374
375# define TTHREAD_TLS_SET(type,name,value) \
376 do { \
377 void *_ptr = pthread_getspecific(_##name##_key); \
378 assert (NULL != _ptr); \
379 *((type*)_ptr) = (value); \
380 } while (0)
381
382# define TTHREAD_TLS_GET(type,name) \
383 *((type*)pthread_getspecific(_##name##_key))
384
385# define TTHREAD_TLS_FREE(name) \
386 pthread_key_delete(_##name##_key);
387
388#else
389
390#error "No Thread Local Storage (TLS) technology for this platform specified."
391
392#endif
393
394#endif // __cplusplus
395
396#endif
397
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:87
int type
Definition: TGX11.cxx:120
Binding & operator=(OUT(*fun)(void))
typedef void((*Func_t)())
double T(double x)
Definition: ChebyshevPol.h:34
const char * Array