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