1818#ifndef SWIFT_RUNTIME_THREADLOCAL_H
1919#define SWIFT_RUNTIME_THREADLOCAL_H
2020
21+ #include < type_traits>
22+ #include " ThreadLocalStorage.h"
23+
2124// / SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL - Does the current configuration
2225// / allow the use of SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL?
23- #if defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME)
26+ #if defined(__APPLE__)
27+ // The pthread TLS APIs work better than C++ TLS on Apple platforms.
28+ #define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 0
29+ #elif defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME)
2430// We define SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL to nothing in this
2531// configuration and just use a global variable, so this is okay.
2632#define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 1
5763#endif
5864
5965namespace swift {
66+ // Validate a type stored in thread-local storage, using static asserts. Such
67+ // types must fit in a pointer and be trivially copyable/destructible.
68+ #define VALIDATE_THREAD_LOCAL_TYPE (T ) \
69+ static_assert (sizeof (T) <= sizeof (void *), \
70+ " cannot store more than a pointer" ); \
71+ static_assert (std::is_trivially_copyable<T>::value, \
72+ " ThreadLocal values must be trivially copyable" ); \
73+ static_assert (std::is_trivially_destructible<T>::value, \
74+ " ThreadLocal cleanup is not supported, stored types must be " \
75+ " trivially destructible" );
76+
6077// A wrapper class for thread-local storage.
6178//
6279// - On platforms that report SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
@@ -72,50 +89,70 @@ namespace swift {
7289// - On platforms that don't report SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL,
7390// we have to simulate thread-local storage. Fortunately, all of
7491// these platforms (at least for now) support pthread_getspecific.
92+ #if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
7593template <class T >
7694class ThreadLocal {
77- static_assert ( sizeof (T) <= sizeof ( void *), " cannot store more than a pointer " );
95+ VALIDATE_THREAD_LOCAL_TYPE (T)
7896
79- #if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
8097 T value;
98+
99+ public:
100+ constexpr ThreadLocal () {}
101+
102+ T get () { return value; }
103+
104+ void set (T newValue) { value = newValue; }
105+ };
81106#else
107+ // A wrapper around a pthread_key_t that is lazily initialized using
108+ // dispatch_once.
109+ class ThreadLocalKey {
82110 // We rely on the zero-initialization of objects with static storage
83111 // duration.
84112 dispatch_once_t once;
85113 pthread_key_t key;
86114
115+ public:
87116 pthread_key_t getKey () {
88- dispatch_once_f (&once, this , [](void *ctx) {
89- pthread_key_create (& reinterpret_cast <ThreadLocal *>(ctx)-> key , nullptr );
117+ dispatch_once_f (&once, &key , [](void *ctx) {
118+ pthread_key_create (reinterpret_cast <pthread_key_t *>(ctx), nullptr );
90119 });
91120 return key;
92121 }
93- #endif
122+ };
123+
124+ // A type representing a constant pthread_key_t, for use on platforms that
125+ // provide reserved keys.
126+ template <pthread_key_t constantKey>
127+ class ConstantThreadLocalKey {
128+ public:
129+ pthread_key_t getKey () { return constantKey; }
130+ };
131+
132+ template <class T , class Key >
133+ class ThreadLocal {
134+ VALIDATE_THREAD_LOCAL_TYPE (T)
135+
136+ Key key;
94137
95138public:
96139 constexpr ThreadLocal () {}
97140
98141 T get () {
99- #if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
100- return value;
101- #else
102- void *storedValue = pthread_getspecific (getKey ());
142+ void *storedValue = SWIFT_THREAD_GETSPECIFIC (key.getKey ());
103143 T value;
104144 memcpy (&value, &storedValue, sizeof (T));
105145 return value;
106- #endif
107146 }
108147
109148 void set (T newValue) {
110- #if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
111- value = newValue;
112- #else
113149 void *storedValue;
114150 memcpy (&storedValue, &newValue, sizeof (T));
115- pthread_setspecific (getKey (), storedValue);
116- #endif
151+ SWIFT_THREAD_SETSPECIFIC (key.getKey (), storedValue);
117152 }
118153};
154+ #endif
155+
119156} // end namespace swift
120157
121158// / SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME) - Declare a variable
@@ -124,13 +161,16 @@ class ThreadLocal {
124161// /
125162// / Because of the fallback path, the default-initialization of the
126163// / type must be equivalent to a bitwise zero-initialization, and the
127- // / type must be small and trivially copyable.
164+ // / type must be small and trivially copyable and destructible .
128165#if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
129- #define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL (TYPE, NAME ) \
166+ #define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL (TYPE, NAME, KEY ) \
130167 SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL swift::ThreadLocal<TYPE> NAME
168+ #elif SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC
169+ #define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL (TYPE, NAME, KEY ) \
170+ swift::ThreadLocal<TYPE, ConstantThreadLocalKey<KEY>> NAME
131171#else
132- #define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL (TYPE, NAME ) \
133- swift::ThreadLocal<TYPE> NAME
172+ #define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL (TYPE, NAME, KEY ) \
173+ swift::ThreadLocal<TYPE, ThreadLocalKey > NAME
134174#endif
135175
136176#endif
0 commit comments