Chromium Code Reviews| Index: src/IceTLS.h |
| diff --git a/src/IceTLS.h b/src/IceTLS.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..2f7889ea5b841d472089e04e96f8f19839c588b1 |
| --- /dev/null |
| +++ b/src/IceTLS.h |
| @@ -0,0 +1,95 @@ |
| +//===- subzero/src/IceTLS.h - thread_local workaround -----------*- C++ -*-===// |
| +// |
| +// The Subzero Code Generator |
| +// |
| +// This file is distributed under the University of Illinois Open Source |
| +// License. See LICENSE.TXT for details. |
| +// |
| +//===----------------------------------------------------------------------===// |
| +// |
| +// This file defines macros for working around the lack of support for |
| +// thread_local in MacOS 10.6. It assumes std::thread is written in |
| +// terms of pthread. Define ICE_THREAD_LOCAL_HACK to enable the |
| +// pthread workarounds. |
| +// |
| +//===----------------------------------------------------------------------===// |
| + |
| +#ifndef SUBZERO_SRC_ICETLS_H |
| +#define SUBZERO_SRC_ICETLS_H |
| + |
| +#if defined(_MSC_VER) |
| +#define ICE_ATTRIBUTE_TLS __declspec(thread) |
| +#else // !_MSC_VER |
| +#define ICE_ATTRIBUTE_TLS thread_local |
| +#endif // !_MSC_VER |
| + |
| +// Defines 4 macros for unifying thread_local and pthread: |
| +// |
| +// ICE_TLS_DECLARE_FIELD(Type, FieldName): Declare a static |
| +// thread_local field inside the current class definition. "Type" |
| +// needs to be a pointer type, such as int* or class Foo*. |
| +// |
| +// ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName): Define a static |
| +// thread_local field outside of its class definition. The field will |
| +// ultimately be initialized to nullptr. |
| +// |
| +// ICE_TLS_INIT_FIELD(FieldName): Ensure the thread_local field is |
| +// properly initialized. This is intended to be called from within a |
| +// static method of the field's class after main() starts (to ensure |
| +// that the pthread library is fully initialized) but before any uses |
| +// of ICE_TLS_GET_FIELD or ICE_TLS_SET_FIELD. |
| +// |
| +// ICE_TLS_GET_FIELD(Type, FieldName): Read the value of the static |
| +// thread_local field. Must be done within the context of its class. |
| +// |
| +// ICE_TLS_SET_FIELD(FieldName, Value): Write a value into the static |
| +// thread_local field. Must be done within the context of its class. |
| + |
| +// TODO(stichnot): Limit this define to only the platforms that |
| +// absolutely require it. And ideally, eventually remove this hack |
| +// altogether. |
| +#define ICE_THREAD_LOCAL_HACK |
| +#ifdef ICE_THREAD_LOCAL_HACK |
| + |
| +// For a static thread_local field F of a class C, instead of |
| +// declaring and defining C::F, we create two static fields: |
| +// static pthread_key_t F__key; |
| +// static int F__dummy; |
| +// |
| +// The F__dummy field is just used to hold the result of the |
| +// pthread_key_create() call, which is executed as a static |
| +// initializer. The F__key field is used as the argument to |
| +// pthread_getspecific() and pthread_setspecific(). |
| + |
| +#include <pthread.h> |
| + |
| +#define ICE_TLS_DECLARE_FIELD(Type, FieldName) \ |
| + typedef Type FieldName##__type; \ |
| + static pthread_key_t FieldName##__key; \ |
| + static int FieldName##__dummy |
| +#define ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName) \ |
| + pthread_key_t ClassName::FieldName##__key; \ |
| + int ClassName::FieldName##__dummy = !!"Silly non-conforming compiler"; |
| +#define ICE_TLS_INIT_FIELD(FieldName) \ |
| + if (FieldName##__dummy) \ |
| + FieldName##__dummy = pthread_key_create(&FieldName##__key, nullptr) |
|
JF
2015/01/25 23:05:05
You should probably handle non-zero returns proper
Jim Stichnoth
2015/01/26 05:43:37
Done, though I didn't feel like there's much reaso
|
| +#define ICE_TLS_GET_FIELD(FieldName) \ |
| + (assert(FieldName##__dummy == 0), \ |
| + static_cast<FieldName##__type>(pthread_getspecific(FieldName##__key))) |
| +#define ICE_TLS_SET_FIELD(FieldName, Value) \ |
| + (assert(FieldName##__dummy == 0), \ |
| + pthread_setspecific(FieldName##__key, (Value))) |
| + |
| +#else // !ICE_THREAD_LOCAL_HACK |
| + |
| +#define ICE_TLS_DECLARE_FIELD(Type, FieldName) \ |
| + static ICE_ATTRIBUTE_TLS Type FieldName |
| +#define ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName) \ |
| + ICE_ATTRIBUTE_TLS Type ClassName::FieldName = nullptr |
| +#define ICE_TLS_INIT_FIELD(FieldName) |
| +#define ICE_TLS_GET_FIELD(FieldName) (FieldName) |
| +#define ICE_TLS_SET_FIELD(FieldName, Value) (FieldName = (Value)) |
| + |
| +#endif // !ICE_THREAD_LOCAL_HACK |
| + |
| +#endif // SUBZERO_SRC_ICETLS_H |