Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 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.
40 *
41 * For simple type use:
42 * TTHREAD_TLS(int) varname;
43 *
44 * For array of simple type use:
45 * TTHREAD_TLS_ARRAY(int, arraysize, varname);
46 *
47 * For object use:
48 * TTHREAD_TLS_DECL(classname, varname);
49 * TTHREAD_TLS_DECL_ARG(classname, varname, arg);
50 * TTHREAD_TLS_DECL_ARG2(classname, varname, arg1, arg2);
51 *
52 */
53
54#ifndef ROOT_ThreadLocalStorage
55#define ROOT_ThreadLocalStorage
56
57#include <stddef.h>
58
59#ifdef __cplusplus
60#include "RtypesCore.h"
61#endif
62
63#include <ROOT/RConfig.hxx>
64
65#include "RConfigure.h"
66
67#if defined(R__MACOSX)
68# if defined(__clang__) && defined(MAC_OS_X_VERSION_10_7) && (defined(__x86_64__) || defined(__i386__))
69# define R__HAS___THREAD
70# elif !defined(R__HAS_PTHREAD)
71# define R__HAS_PTHREAD
72# endif
73#endif
74#if defined(R__LINUX) || defined(R__AIX)
75# define R__HAS___THREAD
76#endif
77#if defined(R__SOLARIS) && !defined(R__HAS_PTHREAD)
78# define R__HAS_PTHREAD
79#endif
80#if defined(R__WIN32)
81# define R__HAS_DECLSPEC_THREAD
82#endif
83#if defined(R__FBSD)
84# define R__HAS_PTHREAD
85#endif
86
87#ifdef __cplusplus
88
89// Note that the order is relevant, more than one of the flag might be
90// on at the same time and we want to use 'best' option available.
91
92# define TTHREAD_TLS(type) thread_local type
93# define TTHREAD_TLS_ARRAY(type,size,name) thread_local type name[size]
94# define TTHREAD_TLS_PTR(name) &name
95
96# define TTHREAD_TLS_DECL(type, name) thread_local type name
97# define TTHREAD_TLS_DECL_ARG(type, name, arg) thread_local type name(arg)
98# define TTHREAD_TLS_DECL_ARG2(type, name, arg1, arg2) thread_local type name(arg1,arg2)
99
100// Available on all platforms
101
102
103// Neither TTHREAD_TLS_DECL_IMPL and TTHREAD_TLS_INIT
104// do not delete the object at the end of the process.
105
106#define TTHREAD_TLS_DECL_IMPL(type, name, ptr, arg) \
107 TTHREAD_TLS(type *) ptr = 0; \
108 if (!ptr) ptr = new type(arg); \
109 type &name = *ptr;
110
111#define TTHREAD_TLS_DECL_IMPL2(type, name, ptr, arg1, arg2) \
112 TTHREAD_TLS(type *) ptr = 0; \
113 if (!ptr) ptr = new type(arg1,arg2); \
114 type &name = *ptr;
115
116#ifndef TTHREAD_TLS_DECL
117
118#define TTHREAD_TLS_DECL(type, name) \
119 TTHREAD_TLS_DECL_IMPL(type,name,_R__JOIN_(ptr,__LINE__),)
120
121#define TTHREAD_TLS_DECL_ARG(type, name, arg) \
122 TTHREAD_TLS_DECL_IMPL(type,name,_R__JOIN_(ptr,__LINE__),arg)
123
124#define TTHREAD_TLS_DECL_ARG2(type, name, arg1, arg2) \
125 TTHREAD_TLS_DECL_IMPL2(type,name,_R__JOIN_(ptr,__LINE__),arg1,arg2)
126
127#endif
128
129template <int marker, typename T>
130T &TTHREAD_TLS_INIT() {
131 TTHREAD_TLS(T*) ptr = NULL;
132 TTHREAD_TLS(Bool_t) isInit(kFALSE);
133 if (!isInit) {
134 ptr = new T;
135 isInit = kTRUE;
136 }
137 return *ptr;
138}
139
140template <int marker, typename Array, typename T>
141Array &TTHREAD_TLS_INIT_ARRAY() {
142 TTHREAD_TLS(Array*) ptr = NULL;
143 TTHREAD_TLS(Bool_t) isInit(kFALSE);
144 if (!isInit) {
145 ptr = new Array[sizeof(Array)/sizeof(T)];
146 isInit = kTRUE;
147 }
148 return *ptr;
149}
150
151template <int marker, typename T, typename ArgType>
152T &TTHREAD_TLS_INIT(ArgType arg) {
153 TTHREAD_TLS(T*) ptr = NULL;
154 TTHREAD_TLS(Bool_t) isInit(kFALSE);
155 if (!isInit) {
156 ptr = new T(arg);
157 isInit = kTRUE;
158 }
159 return *ptr;
160}
161
162#else // __cplusplus
163
164// TODO: Evaluate using thread_local / _Thread_local from C11 instead of
165// platform-specific solutions such as __thread, __declspec(thread) or the
166// pthreads API functions.
167
168#if defined(R__HAS___THREAD)
169
170# define TTHREAD_TLS_DECLARE(type,name)
171# define TTHREAD_TLS_INIT(type,name,value) static __thread type name = (value)
172# define TTHREAD_TLS_SET(type,name,value) name = (value)
173# define TTHREAD_TLS_GET(type,name) (name)
174# define TTHREAD_TLS_FREE(name)
175
176#elif defined(R__HAS_DECLSPEC_THREAD)
177
178# define TTHREAD_TLS_DECLARE(type,name)
179# define TTHREAD_TLS_INIT(type,name,value) static __declspec(thread) type name = (value)
180# define TTHREAD_TLS_SET(type,name,value) name = (value)
181# define TTHREAD_TLS_GET(type,name) (name)
182# define TTHREAD_TLS_FREE(name)
183
184#elif defined(R__HAS_PTHREAD)
185
186#include <assert.h>
187#include <pthread.h>
188
189# define TTHREAD_TLS_DECLARE(type,name) \
190 static pthread_key_t _##name##_key; \
191 static void _##name##_key_delete(void * arg) \
192 { \
193 assert (NULL != arg); \
194 free(arg); \
195 } \
196 static void _##name##_key_create(void) \
197 { \
198 int _ret; \
199 _ret = pthread_key_create(&(_##name##_key), _##name##_key_delete); \
200 _ret = _ret; /* To get rid of warnings in case of NDEBUG */ \
201 assert (0 == _ret); \
202 } \
203 static pthread_once_t _##name##_once = PTHREAD_ONCE_INIT;
204
205# define TTHREAD_TLS_INIT(type,name,value) \
206 do { \
207 void *_ptr; \
208 (void) pthread_once(&(_##name##_once), _##name##_key_create); \
209 if ((_ptr = pthread_getspecific(_##name##_key)) == NULL) { \
210 _ptr = malloc(sizeof(type)); \
211 assert (NULL != _ptr); \
212 (void) pthread_setspecific(_##name##_key, _ptr); \
213 *((type*)_ptr) = (value); \
214 } \
215 } while (0)
216
217# define TTHREAD_TLS_SET(type,name,value) \
218 do { \
219 void *_ptr = pthread_getspecific(_##name##_key); \
220 assert (NULL != _ptr); \
221 *((type*)_ptr) = (value); \
222 } while (0)
223
224# define TTHREAD_TLS_GET(type,name) \
225 *((type*)pthread_getspecific(_##name##_key))
226
227# define TTHREAD_TLS_FREE(name) \
228 pthread_key_delete(_##name##_key);
229
230#else
231
232#error "No Thread Local Storage (TLS) technology for this platform specified."
233
234#endif
235
236#endif // __cplusplus
237
238#endif
239
bool Bool_t
Definition RtypesCore.h:63
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
double T(double x)
const char * Array