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 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
136template <int marker, typename T>
137T &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
147template <int marker, typename Array, typename T>
148Array &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
158template <int marker, typename T, typename ArgType>
159T &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
const Bool_t kFALSE
Definition: RtypesCore.h:101
bool Bool_t
Definition: RtypesCore.h:63
const Bool_t kTRUE
Definition: RtypesCore.h:100
double T(double x)
Definition: ChebyshevPol.h:34
const char * Array