| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2009 Jian Li <jianli@chromium.org> | 3 * Copyright (C) 2009 Jian Li <jianli@chromium.org> |
| 4 * Copyright (C) 2012 Patrick Gansterer <paroga@paroga.com> | 4 * Copyright (C) 2012 Patrick Gansterer <paroga@paroga.com> |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 8 * are met: | 8 * are met: |
| 9 * | 9 * |
| 10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 | 51 |
| 52 #if OS(POSIX) | 52 #if OS(POSIX) |
| 53 #include <pthread.h> | 53 #include <pthread.h> |
| 54 #elif OS(WIN) | 54 #elif OS(WIN) |
| 55 #include <windows.h> | 55 #include <windows.h> |
| 56 #endif | 56 #endif |
| 57 | 57 |
| 58 namespace WTF { | 58 namespace WTF { |
| 59 | 59 |
| 60 #if OS(WIN) | 60 #if OS(WIN) |
| 61 // ThreadSpecificThreadExit should be called each time when a thread is detached
. | 61 // ThreadSpecificThreadExit should be called each time when a thread is |
| 62 // detached. |
| 62 // This is done automatically for threads created with WTF::createThread. | 63 // This is done automatically for threads created with WTF::createThread. |
| 63 WTF_EXPORT void ThreadSpecificThreadExit(); | 64 WTF_EXPORT void ThreadSpecificThreadExit(); |
| 64 #endif | 65 #endif |
| 65 | 66 |
| 66 template <typename T> | 67 template <typename T> |
| 67 class ThreadSpecific { | 68 class ThreadSpecific { |
| 68 USING_FAST_MALLOC(ThreadSpecific); | 69 USING_FAST_MALLOC(ThreadSpecific); |
| 69 WTF_MAKE_NONCOPYABLE(ThreadSpecific); | 70 WTF_MAKE_NONCOPYABLE(ThreadSpecific); |
| 70 | 71 |
| 71 public: | 72 public: |
| 72 ThreadSpecific(); | 73 ThreadSpecific(); |
| 73 bool | 74 bool |
| 74 isSet(); // Useful as a fast check to see if this thread has set this value. | 75 isSet(); // Useful as a fast check to see if this thread has set this value. |
| 75 T* operator->(); | 76 T* operator->(); |
| 76 operator T*(); | 77 operator T*(); |
| 77 T& operator*(); | 78 T& operator*(); |
| 78 | 79 |
| 79 private: | 80 private: |
| 80 #if OS(WIN) | 81 #if OS(WIN) |
| 81 WTF_EXPORT friend void ThreadSpecificThreadExit(); | 82 WTF_EXPORT friend void ThreadSpecificThreadExit(); |
| 82 #endif | 83 #endif |
| 83 | 84 |
| 84 // Not implemented. It's technically possible to destroy a thread specific key
, but one would need | 85 // Not implemented. It's technically possible to destroy a thread specific |
| 85 // to make sure that all values have been destroyed already (usually, that all
threads that used it | 86 // key, but one would need to make sure that all values have been destroyed |
| 86 // have exited). It's unlikely that any user of this call will be in that situ
ation - and having | 87 // already (usually, that all threads that used it have exited). It's |
| 87 // a destructor defined can be confusing, given that it has such strong pre-re
quisites to work correctly. | 88 // unlikely that any user of this call will be in that situation - and having |
| 89 // a destructor defined can be confusing, given that it has such strong |
| 90 // pre-requisites to work correctly. |
| 88 ~ThreadSpecific(); | 91 ~ThreadSpecific(); |
| 89 | 92 |
| 90 T* get(); | 93 T* get(); |
| 91 void set(T*); | 94 void set(T*); |
| 92 void static destroy(void* ptr); | 95 void static destroy(void* ptr); |
| 93 | 96 |
| 94 struct Data { | 97 struct Data { |
| 95 WTF_MAKE_NONCOPYABLE(Data); | 98 WTF_MAKE_NONCOPYABLE(Data); |
| 96 | 99 |
| 97 public: | 100 public: |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 pthread_setspecific(m_key, new Data(ptr, this)); | 158 pthread_setspecific(m_key, new Data(ptr, this)); |
| 156 } | 159 } |
| 157 | 160 |
| 158 #elif OS(WIN) | 161 #elif OS(WIN) |
| 159 | 162 |
| 160 // TLS_OUT_OF_INDEXES is not defined on WinCE. | 163 // TLS_OUT_OF_INDEXES is not defined on WinCE. |
| 161 #ifndef TLS_OUT_OF_INDEXES | 164 #ifndef TLS_OUT_OF_INDEXES |
| 162 #define TLS_OUT_OF_INDEXES 0xffffffff | 165 #define TLS_OUT_OF_INDEXES 0xffffffff |
| 163 #endif | 166 #endif |
| 164 | 167 |
| 165 // The maximum number of TLS keys that can be created. For simplification, we as
sume that: | 168 // The maximum number of TLS keys that can be created. For simplification, we |
| 166 // 1) Once the instance of ThreadSpecific<> is created, it will not be destructe
d until the program dies. | 169 // assume that: |
| 167 // 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed
number should be far enough. | 170 // 1) Once the instance of ThreadSpecific<> is created, it will not be |
| 171 // destructed until the program dies. |
| 172 // 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed |
| 173 // number should be far enough. |
| 168 const int kMaxTlsKeySize = 256; | 174 const int kMaxTlsKeySize = 256; |
| 169 | 175 |
| 170 WTF_EXPORT long& tlsKeyCount(); | 176 WTF_EXPORT long& tlsKeyCount(); |
| 171 WTF_EXPORT DWORD* tlsKeys(); | 177 WTF_EXPORT DWORD* tlsKeys(); |
| 172 | 178 |
| 173 class PlatformThreadSpecificKey; | 179 class PlatformThreadSpecificKey; |
| 174 typedef PlatformThreadSpecificKey* ThreadSpecificKey; | 180 typedef PlatformThreadSpecificKey* ThreadSpecificKey; |
| 175 | 181 |
| 176 WTF_EXPORT void threadSpecificKeyCreate(ThreadSpecificKey*, void (*)(void*)); | 182 WTF_EXPORT void threadSpecificKeyCreate(ThreadSpecificKey*, void (*)(void*)); |
| 177 WTF_EXPORT void threadSpecificKeyDelete(ThreadSpecificKey); | 183 WTF_EXPORT void threadSpecificKeyDelete(ThreadSpecificKey); |
| 178 WTF_EXPORT void threadSpecificSet(ThreadSpecificKey, void*); | 184 WTF_EXPORT void threadSpecificSet(ThreadSpecificKey, void*); |
| 179 WTF_EXPORT void* threadSpecificGet(ThreadSpecificKey); | 185 WTF_EXPORT void* threadSpecificGet(ThreadSpecificKey); |
| 180 | 186 |
| 181 template <typename T> | 187 template <typename T> |
| 182 inline ThreadSpecific<T>::ThreadSpecific() : m_index(-1) { | 188 inline ThreadSpecific<T>::ThreadSpecific() : m_index(-1) { |
| 183 DWORD tlsKey = TlsAlloc(); | 189 DWORD tlsKey = TlsAlloc(); |
| 184 if (tlsKey == TLS_OUT_OF_INDEXES) | 190 if (tlsKey == TLS_OUT_OF_INDEXES) |
| 185 CRASH(); | 191 CRASH(); |
| 186 | 192 |
| 187 m_index = InterlockedIncrement(&tlsKeyCount()) - 1; | 193 m_index = InterlockedIncrement(&tlsKeyCount()) - 1; |
| 188 if (m_index >= kMaxTlsKeySize) | 194 if (m_index >= kMaxTlsKeySize) |
| 189 CRASH(); | 195 CRASH(); |
| 190 tlsKeys()[m_index] = tlsKey; | 196 tlsKeys()[m_index] = tlsKey; |
| 191 } | 197 } |
| 192 | 198 |
| 193 template <typename T> | 199 template <typename T> |
| 194 inline ThreadSpecific<T>::~ThreadSpecific() { | 200 inline ThreadSpecific<T>::~ThreadSpecific() { |
| 195 // Does not invoke destructor functions. They will be called from ThreadSpecif
icThreadExit when the thread is detached. | 201 // Does not invoke destructor functions. They will be called from |
| 202 // ThreadSpecificThreadExit when the thread is detached. |
| 196 TlsFree(tlsKeys()[m_index]); | 203 TlsFree(tlsKeys()[m_index]); |
| 197 } | 204 } |
| 198 | 205 |
| 199 template <typename T> | 206 template <typename T> |
| 200 inline T* ThreadSpecific<T>::get() { | 207 inline T* ThreadSpecific<T>::get() { |
| 201 Data* data = static_cast<Data*>(TlsGetValue(tlsKeys()[m_index])); | 208 Data* data = static_cast<Data*>(TlsGetValue(tlsKeys()[m_index])); |
| 202 return data ? data->value : 0; | 209 return data ? data->value : 0; |
| 203 } | 210 } |
| 204 | 211 |
| 205 template <typename T> | 212 template <typename T> |
| 206 inline void ThreadSpecific<T>::set(T* ptr) { | 213 inline void ThreadSpecific<T>::set(T* ptr) { |
| 207 ASSERT(!get()); | 214 ASSERT(!get()); |
| 208 Data* data = new Data(ptr, this); | 215 Data* data = new Data(ptr, this); |
| 209 data->destructor = &ThreadSpecific<T>::destroy; | 216 data->destructor = &ThreadSpecific<T>::destroy; |
| 210 TlsSetValue(tlsKeys()[m_index], data); | 217 TlsSetValue(tlsKeys()[m_index], data); |
| 211 } | 218 } |
| 212 | 219 |
| 213 #else | 220 #else |
| 214 #error ThreadSpecific is not implemented for this platform. | 221 #error ThreadSpecific is not implemented for this platform. |
| 215 #endif | 222 #endif |
| 216 | 223 |
| 217 template <typename T> | 224 template <typename T> |
| 218 inline void ThreadSpecific<T>::destroy(void* ptr) { | 225 inline void ThreadSpecific<T>::destroy(void* ptr) { |
| 219 if (isShutdown()) | 226 if (isShutdown()) |
| 220 return; | 227 return; |
| 221 | 228 |
| 222 Data* data = static_cast<Data*>(ptr); | 229 Data* data = static_cast<Data*>(ptr); |
| 223 | 230 |
| 224 #if OS(POSIX) | 231 #if OS(POSIX) |
| 225 // We want get() to keep working while data destructor works, because it can b
e called indirectly by the destructor. | 232 // We want get() to keep working while data destructor works, because it can |
| 226 // Some pthreads implementations zero out the pointer before calling destroy()
, so we temporarily reset it. | 233 // be called indirectly by the destructor. Some pthreads implementations |
| 234 // zero out the pointer before calling destroy(), so we temporarily reset it. |
| 227 pthread_setspecific(data->owner->m_key, ptr); | 235 pthread_setspecific(data->owner->m_key, ptr); |
| 228 #endif | 236 #endif |
| 229 | 237 |
| 230 data->value->~T(); | 238 data->value->~T(); |
| 231 Partitions::fastFree(data->value); | 239 Partitions::fastFree(data->value); |
| 232 | 240 |
| 233 #if OS(POSIX) | 241 #if OS(POSIX) |
| 234 pthread_setspecific(data->owner->m_key, 0); | 242 pthread_setspecific(data->owner->m_key, 0); |
| 235 #elif OS(WIN) | 243 #elif OS(WIN) |
| 236 TlsSetValue(tlsKeys()[data->owner->m_index], 0); | 244 TlsSetValue(tlsKeys()[data->owner->m_index], 0); |
| 237 #else | 245 #else |
| 238 #error ThreadSpecific is not implemented for this platform. | 246 #error ThreadSpecific is not implemented for this platform. |
| 239 #endif | 247 #endif |
| 240 | 248 |
| 241 delete data; | 249 delete data; |
| 242 } | 250 } |
| 243 | 251 |
| 244 template <typename T> | 252 template <typename T> |
| 245 inline bool ThreadSpecific<T>::isSet() { | 253 inline bool ThreadSpecific<T>::isSet() { |
| 246 return !!get(); | 254 return !!get(); |
| 247 } | 255 } |
| 248 | 256 |
| 249 template <typename T> | 257 template <typename T> |
| 250 inline ThreadSpecific<T>::operator T*() { | 258 inline ThreadSpecific<T>::operator T*() { |
| 251 T* ptr = static_cast<T*>(get()); | 259 T* ptr = static_cast<T*>(get()); |
| 252 if (!ptr) { | 260 if (!ptr) { |
| 253 // Set up thread-specific value's memory pointer before invoking constructor
, in case any function it calls | 261 // Set up thread-specific value's memory pointer before invoking |
| 262 // constructor, in case any function it calls |
| 254 // needs to access the value, to avoid recursion. | 263 // needs to access the value, to avoid recursion. |
| 255 ptr = static_cast<T*>(Partitions::fastZeroedMalloc( | 264 ptr = static_cast<T*>(Partitions::fastZeroedMalloc( |
| 256 sizeof(T), WTF_HEAP_PROFILER_TYPE_NAME(T))); | 265 sizeof(T), WTF_HEAP_PROFILER_TYPE_NAME(T))); |
| 257 set(ptr); | 266 set(ptr); |
| 258 new (NotNull, ptr) T; | 267 new (NotNull, ptr) T; |
| 259 } | 268 } |
| 260 return ptr; | 269 return ptr; |
| 261 } | 270 } |
| 262 | 271 |
| 263 template <typename T> | 272 template <typename T> |
| 264 inline T* ThreadSpecific<T>::operator->() { | 273 inline T* ThreadSpecific<T>::operator->() { |
| 265 return operator T*(); | 274 return operator T*(); |
| 266 } | 275 } |
| 267 | 276 |
| 268 template <typename T> | 277 template <typename T> |
| 269 inline T& ThreadSpecific<T>::operator*() { | 278 inline T& ThreadSpecific<T>::operator*() { |
| 270 return *operator T*(); | 279 return *operator T*(); |
| 271 } | 280 } |
| 272 | 281 |
| 273 } // namespace WTF | 282 } // namespace WTF |
| 274 | 283 |
| 275 using WTF::ThreadSpecific; | 284 using WTF::ThreadSpecific; |
| 276 | 285 |
| 277 #endif // WTF_ThreadSpecific_h | 286 #endif // WTF_ThreadSpecific_h |
| OLD | NEW |