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#ifdef __CINT__
93
94# define TTHREAD_TLS(type) static type
95# define TTHREAD_TLS_ARRAY(type,size,name) static type name[size]
96# define TTHREAD_TLS_PTR(name) &name
97
98#else
99
100# define TTHREAD_TLS(type) thread_local type
101# define TTHREAD_TLS_ARRAY(type,size,name) thread_local type name[size]
102# define TTHREAD_TLS_PTR(name) &name
103
104# define TTHREAD_TLS_DECL(type, name) thread_local type name
105# define TTHREAD_TLS_DECL_ARG(type, name, arg) thread_local type name(arg)
106# define TTHREAD_TLS_DECL_ARG2(type, name, arg1, arg2) thread_local type name(arg1,arg2)
107
108#endif
109
110// Available on all platforms
111
112
113// Neither TTHREAD_TLS_DECL_IMPL and TTHREAD_TLS_INIT
114// do not delete the object at the end of the process.
115
116#define TTHREAD_TLS_DECL_IMPL(type, name, ptr, arg) \
117 TTHREAD_TLS(type *) ptr = 0; \
118 if (!ptr) ptr = new type(arg); \
119 type &name = *ptr;
120
121#define TTHREAD_TLS_DECL_IMPL2(type, name, ptr, arg1, arg2) \
122 TTHREAD_TLS(type *) ptr = 0; \
123 if (!ptr) ptr = new type(arg1,arg2); \
124 type &name = *ptr;
125
126#ifndef TTHREAD_TLS_DECL
127
128#define TTHREAD_TLS_DECL(type, name) \
129 TTHREAD_TLS_DECL_IMPL(type,name,_R__JOIN_(ptr,__LINE__),)
130
131#define TTHREAD_TLS_DECL_ARG(type, name, arg) \
132 TTHREAD_TLS_DECL_IMPL(type,name,_R__JOIN_(ptr,__LINE__),arg)
133
134#define TTHREAD_TLS_DECL_ARG2(type, name, arg1, arg2) \
135 TTHREAD_TLS_DECL_IMPL2(type,name,_R__JOIN_(ptr,__LINE__),arg1,arg2)
136
137#endif
138
139template <int marker, typename T>
140T &TTHREAD_TLS_INIT() {
141 TTHREAD_TLS(T*) ptr = NULL;
142 TTHREAD_TLS(Bool_t) isInit(kFALSE);
143 if (!isInit) {
144 ptr = new T;
145 isInit = kTRUE;
146 }
147 return *ptr;
148}
149
150template <int marker, typename Array, typename T>
151Array &TTHREAD_TLS_INIT_ARRAY() {
152 TTHREAD_TLS(Array*) ptr = NULL;
153 TTHREAD_TLS(Bool_t) isInit(kFALSE);
154 if (!isInit) {
155 ptr = new Array[sizeof(Array)/sizeof(T)];
156 isInit = kTRUE;
157 }
158 return *ptr;
159}
160
161template <int marker, typename T, typename ArgType>
162T &TTHREAD_TLS_INIT(ArgType arg) {
163 TTHREAD_TLS(T*) ptr = NULL;
164 TTHREAD_TLS(Bool_t) isInit(kFALSE);
165 if (!isInit) {
166 ptr = new T(arg);
167 isInit = kTRUE;
168 }
169 return *ptr;
170}
171
172#else // __cplusplus
173
174// TODO: Evaluate using thread_local / _Thread_local from C11 instead of
175// platform-specific solutions such as __thread, __declspec(thread) or the
176// pthreads API functions.
177
178#if defined(R__HAS___THREAD)
179
180# define TTHREAD_TLS_DECLARE(type,name)
181# define TTHREAD_TLS_INIT(type,name,value) static __thread type name = (value)
182# define TTHREAD_TLS_SET(type,name,value) name = (value)
183# define TTHREAD_TLS_GET(type,name) (name)
184# define TTHREAD_TLS_FREE(name)
185
186#elif defined(R__HAS_DECLSPEC_THREAD)
187
188# define TTHREAD_TLS_DECLARE(type,name)
189# define TTHREAD_TLS_INIT(type,name,value) static __declspec(thread) type name = (value)
190# define TTHREAD_TLS_SET(type,name,value) name = (value)
191# define TTHREAD_TLS_GET(type,name) (name)
192# define TTHREAD_TLS_FREE(name)
193
194#elif defined(R__HAS_PTHREAD)
195
196#include <assert.h>
197#include <pthread.h>
198
199# define TTHREAD_TLS_DECLARE(type,name) \
200 static pthread_key_t _##name##_key; \
201 static void _##name##_key_delete(void * arg) \
202 { \
203 assert (NULL != arg); \
204 free(arg); \
205 } \
206 static void _##name##_key_create(void) \
207 { \
208 int _ret; \
209 _ret = pthread_key_create(&(_##name##_key), _##name##_key_delete); \
210 _ret = _ret; /* To get rid of warnings in case of NDEBUG */ \
211 assert (0 == _ret); \
212 } \
213 static pthread_once_t _##name##_once = PTHREAD_ONCE_INIT;
214
215# define TTHREAD_TLS_INIT(type,name,value) \
216 do { \
217 void *_ptr; \
218 (void) pthread_once(&(_##name##_once), _##name##_key_create); \
219 if ((_ptr = pthread_getspecific(_##name##_key)) == NULL) { \
220 _ptr = malloc(sizeof(type)); \
221 assert (NULL != _ptr); \
222 (void) pthread_setspecific(_##name##_key, _ptr); \
223 *((type*)_ptr) = (value); \
224 } \
225 } while (0)
226
227# define TTHREAD_TLS_SET(type,name,value) \
228 do { \
229 void *_ptr = pthread_getspecific(_##name##_key); \
230 assert (NULL != _ptr); \
231 *((type*)_ptr) = (value); \
232 } while (0)
233
234# define TTHREAD_TLS_GET(type,name) \
235 *((type*)pthread_getspecific(_##name##_key))
236
237# define TTHREAD_TLS_FREE(name) \
238 pthread_key_delete(_##name##_key);
239
240#else
241
242#error "No Thread Local Storage (TLS) technology for this platform specified."
243
244#endif
245
246#endif // __cplusplus
247
248#endif
249
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