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 * Original was part of a test-suite or Open MPI, and license was BSD
6 * Author: Rainer Keller, HLRS
7 * Modified: Fons Rademakers, CERN
8 * Modified: Philippe Canal, FNAL
9 *
10 * Thread-local storage (TLS) is not supported on all environments.
11 * This header file and test-program shows how to abstract away, using either
12 * __thread,
13 * __declspec(thread),
14 * thread_local or
15 * Pthread-Keys
16 * depending on the (configure-set) CPP-variables R__HAS___THREAD,
17 * R__HAS_DECLSPEC_THREAD or R__HAS_PTHREAD.
18 *
19 * Use the macros TTHREAD_TLS_DECLARE, TTHREAD_TLS_INIT, and the
20 * getters and setters TTHREAD_TLS_GET and TTHREAD_TLS_GET
21 * to work on the declared variables.
22 *
23 * In case of PThread keys, we need to resolve to using keys!
24 * In order to do so, we need to declare and access
25 * TLS variables through three macros:
26 * - TTHREAD_TLS_DECLARE
27 * - TTHREAD_TLS_INIT
28 * - TTHREAD_TLS_SET and
29 * - TTHREAD_TLS_GET
30 * We do depend on the following (GCC-)extension:
31 * - In case of function-local static functions,
32 * we declare a sub-function to create a specific key.
33 * Unfortunately, we do NOT use the following extensions:
34 * - Using typeof, we could get rid of the type-declaration
35 * which is used for casting, however typeof is not ANSI C.
36 * - We do NOT allow something like
37 * func (a, TTHREAD_TLS_SET(int, my_var, 5));
38 * as we do not use the gcc-extension of returning macro-values.
39 *
40 * C++11 requires the implementation of the thread_local storage.
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)
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#if defined(R__FBSD)
85# define R__HAS_PTHREAD
86#endif
87
88#ifdef __cplusplus
89
90// Note that the order is relevant, more than one of the flag might be
91// on at the same time and we want to use 'best' option available.
92
93# define TTHREAD_TLS(type) thread_local type
94# define TTHREAD_TLS_ARRAY(type,size,name) thread_local type name[size]
95# define TTHREAD_TLS_PTR(name) &name
96
97# define TTHREAD_TLS_DECL(type, name) thread_local type name
98# define TTHREAD_TLS_DECL_ARG(type, name, arg) thread_local type name(arg)
99# define TTHREAD_TLS_DECL_ARG2(type, name, arg1, arg2) thread_local type name(arg1,arg2)
100
101// Available on all platforms
102
103
104// Neither TTHREAD_TLS_DECL_IMPL and TTHREAD_TLS_INIT
105// do not delete the object at the end of the process.
106
107#define TTHREAD_TLS_DECL_IMPL(type, name, ptr, arg) \
108 TTHREAD_TLS(type *) ptr = 0; \
109 if (!ptr) ptr = new type(arg); \
110 type &name = *ptr;
111
112#define TTHREAD_TLS_DECL_IMPL2(type, name, ptr, arg1, arg2) \
113 TTHREAD_TLS(type *) ptr = 0; \
114 if (!ptr) ptr = new type(arg1,arg2); \
115 type &name = *ptr;
116
117#ifndef TTHREAD_TLS_DECL
118
119#define TTHREAD_TLS_DECL(type, name) \
120 TTHREAD_TLS_DECL_IMPL(type,name,_R__JOIN_(ptr,__LINE__),)
121
122#define TTHREAD_TLS_DECL_ARG(type, name, arg) \
123 TTHREAD_TLS_DECL_IMPL(type,name,_R__JOIN_(ptr,__LINE__),arg)
124
125#define TTHREAD_TLS_DECL_ARG2(type, name, arg1, arg2) \
126 TTHREAD_TLS_DECL_IMPL2(type,name,_R__JOIN_(ptr,__LINE__),arg1,arg2)
127
128#endif
129
130template <int marker, typename T>
131T &TTHREAD_TLS_INIT() {
132 TTHREAD_TLS(T*) ptr = NULL;
134 if (!isInit) {
135 ptr = new T;
136 isInit = kTRUE;
137 }
138 return *ptr;
139}
140
141template <int marker, typename Array, typename T>
143 TTHREAD_TLS(Array*) ptr = NULL;
145 if (!isInit) {
146 ptr = new Array[sizeof(Array)/sizeof(T)];
147 isInit = kTRUE;
148 }
149 return *ptr;
150}
151
152template <int marker, typename T, typename ArgType>
154 TTHREAD_TLS(T*) ptr = NULL;
156 if (!isInit) {
157 ptr = new T(arg);
158 isInit = kTRUE;
159 }
160 return *ptr;
161}
162
163#else // __cplusplus
164
165// TODO: Evaluate using thread_local / _Thread_local from C11 instead of
166// platform-specific solutions such as __thread, __declspec(thread) or the
167// pthreads API functions.
168
169#if defined(R__HAS___THREAD)
170
171# define TTHREAD_TLS_DECLARE(type,name)
172# define TTHREAD_TLS_INIT(type,name,value) static __thread type name = (value)
173# define TTHREAD_TLS_SET(type,name,value) name = (value)
174# define TTHREAD_TLS_GET(type,name) (name)
175# define TTHREAD_TLS_FREE(name)
176
177#elif defined(R__HAS_DECLSPEC_THREAD)
178
179# define TTHREAD_TLS_DECLARE(type,name)
180# define TTHREAD_TLS_INIT(type,name,value) static __declspec(thread) type name = (value)
181# define TTHREAD_TLS_SET(type,name,value) name = (value)
182# define TTHREAD_TLS_GET(type,name) (name)
183# define TTHREAD_TLS_FREE(name)
184
185#elif defined(R__HAS_PTHREAD)
186#ifdef __cplusplus
187#include <cassert>
188#else
189#include <assert.h>
190#endif
191#include <pthread.h>
192
193# define TTHREAD_TLS_DECLARE(type,name) \
194 static pthread_key_t _##name##_key; \
195 static void _##name##_key_delete(void * arg) \
196 { \
197 assert (NULL != arg); \
198 free(arg); \
199 } \
200 static void _##name##_key_create(void) \
201 { \
202 int _ret; \
203 _ret = pthread_key_create(&(_##name##_key), _##name##_key_delete); \
204 _ret = _ret; /* To get rid of warnings in case of NDEBUG */ \
205 assert (0 == _ret); \
206 } \
207 static pthread_once_t _##name##_once = PTHREAD_ONCE_INIT;
208
209# define TTHREAD_TLS_INIT(type,name,value) \
210 do { \
211 void *_ptr; \
212 (void) pthread_once(&(_##name##_once), _##name##_key_create); \
213 if ((_ptr = pthread_getspecific(_##name##_key)) == NULL) { \
214 _ptr = malloc(sizeof(type)); \
215 assert (NULL != _ptr); \
216 (void) pthread_setspecific(_##name##_key, _ptr); \
217 *((type*)_ptr) = (value); \
218 } \
219 } while (0)
220
221# define TTHREAD_TLS_SET(type,name,value) \
222 do { \
223 void *_ptr = pthread_getspecific(_##name##_key); \
224 assert (NULL != _ptr); \
225 *((type*)_ptr) = (value); \
226 } while (0)
227
228# define TTHREAD_TLS_GET(type,name) \
229 *((type*)pthread_getspecific(_##name##_key))
230
231# define TTHREAD_TLS_FREE(name) \
232 pthread_key_delete(_##name##_key);
233
234#else
235
236#error "No Thread Local Storage (TLS) technology for this platform specified."
237
238#endif
239
240#endif // __cplusplus
241
242#endif
243
Basic types used by ROOT and required by TInterpreter.
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:78
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
const char * Array