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 30 matching lines...) Expand all Loading... |
41 | 41 |
42 #ifndef WTF_ThreadSpecific_h | 42 #ifndef WTF_ThreadSpecific_h |
43 #define WTF_ThreadSpecific_h | 43 #define WTF_ThreadSpecific_h |
44 | 44 |
45 #include "wtf/Noncopyable.h" | 45 #include "wtf/Noncopyable.h" |
46 #include "wtf/StdLibExtras.h" | 46 #include "wtf/StdLibExtras.h" |
47 #include "wtf/WTFExport.h" | 47 #include "wtf/WTFExport.h" |
48 | 48 |
49 #if USE(PTHREADS) | 49 #if USE(PTHREADS) |
50 #include <pthread.h> | 50 #include <pthread.h> |
51 #elif OS(WINDOWS) | 51 #elif OS(WIN) |
52 #include <windows.h> | 52 #include <windows.h> |
53 #endif | 53 #endif |
54 | 54 |
55 namespace WTF { | 55 namespace WTF { |
56 | 56 |
57 #if OS(WINDOWS) | 57 #if OS(WIN) |
58 // ThreadSpecificThreadExit should be called each time when a thread is detached
. | 58 // ThreadSpecificThreadExit should be called each time when a thread is detached
. |
59 // This is done automatically for threads created with WTF::createThread. | 59 // This is done automatically for threads created with WTF::createThread. |
60 WTF_EXPORT void ThreadSpecificThreadExit(); | 60 WTF_EXPORT void ThreadSpecificThreadExit(); |
61 #endif | 61 #endif |
62 | 62 |
63 template<typename T> class ThreadSpecific { | 63 template<typename T> class ThreadSpecific { |
64 WTF_MAKE_NONCOPYABLE(ThreadSpecific); | 64 WTF_MAKE_NONCOPYABLE(ThreadSpecific); |
65 public: | 65 public: |
66 ThreadSpecific(); | 66 ThreadSpecific(); |
67 bool isSet(); // Useful as a fast check to see if this thread has set this v
alue. | 67 bool isSet(); // Useful as a fast check to see if this thread has set this v
alue. |
68 T* operator->(); | 68 T* operator->(); |
69 operator T*(); | 69 operator T*(); |
70 T& operator*(); | 70 T& operator*(); |
71 | 71 |
72 private: | 72 private: |
73 #if OS(WINDOWS) | 73 #if OS(WIN) |
74 WTF_EXPORT friend void ThreadSpecificThreadExit(); | 74 WTF_EXPORT friend void ThreadSpecificThreadExit(); |
75 #endif | 75 #endif |
76 | 76 |
77 // Not implemented. It's technically possible to destroy a thread specific k
ey, but one would need | 77 // Not implemented. It's technically possible to destroy a thread specific k
ey, but one would need |
78 // to make sure that all values have been destroyed already (usually, that a
ll threads that used it | 78 // to make sure that all values have been destroyed already (usually, that a
ll threads that used it |
79 // have exited). It's unlikely that any user of this call will be in that si
tuation - and having | 79 // have exited). It's unlikely that any user of this call will be in that si
tuation - and having |
80 // a destructor defined can be confusing, given that it has such strong pre-
requisites to work correctly. | 80 // a destructor defined can be confusing, given that it has such strong pre-
requisites to work correctly. |
81 ~ThreadSpecific(); | 81 ~ThreadSpecific(); |
82 | 82 |
83 T* get(); | 83 T* get(); |
84 void set(T*); | 84 void set(T*); |
85 void static destroy(void* ptr); | 85 void static destroy(void* ptr); |
86 | 86 |
87 struct Data { | 87 struct Data { |
88 WTF_MAKE_NONCOPYABLE(Data); | 88 WTF_MAKE_NONCOPYABLE(Data); |
89 public: | 89 public: |
90 Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {} | 90 Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {} |
91 | 91 |
92 T* value; | 92 T* value; |
93 ThreadSpecific<T>* owner; | 93 ThreadSpecific<T>* owner; |
94 #if OS(WINDOWS) | 94 #if OS(WIN) |
95 void (*destructor)(void*); | 95 void (*destructor)(void*); |
96 #endif | 96 #endif |
97 }; | 97 }; |
98 | 98 |
99 #if USE(PTHREADS) | 99 #if USE(PTHREADS) |
100 pthread_key_t m_key; | 100 pthread_key_t m_key; |
101 #elif OS(WINDOWS) | 101 #elif OS(WIN) |
102 int m_index; | 102 int m_index; |
103 #endif | 103 #endif |
104 }; | 104 }; |
105 | 105 |
106 #if USE(PTHREADS) | 106 #if USE(PTHREADS) |
107 | 107 |
108 typedef pthread_key_t ThreadSpecificKey; | 108 typedef pthread_key_t ThreadSpecificKey; |
109 | 109 |
110 inline void threadSpecificKeyCreate(ThreadSpecificKey* key, void (*destructor)(v
oid *)) | 110 inline void threadSpecificKeyCreate(ThreadSpecificKey* key, void (*destructor)(v
oid *)) |
111 { | 111 { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 return data ? data->value : 0; | 146 return data ? data->value : 0; |
147 } | 147 } |
148 | 148 |
149 template<typename T> | 149 template<typename T> |
150 inline void ThreadSpecific<T>::set(T* ptr) | 150 inline void ThreadSpecific<T>::set(T* ptr) |
151 { | 151 { |
152 ASSERT(!get()); | 152 ASSERT(!get()); |
153 pthread_setspecific(m_key, new Data(ptr, this)); | 153 pthread_setspecific(m_key, new Data(ptr, this)); |
154 } | 154 } |
155 | 155 |
156 #elif OS(WINDOWS) | 156 #elif OS(WIN) |
157 | 157 |
158 // TLS_OUT_OF_INDEXES is not defined on WinCE. | 158 // TLS_OUT_OF_INDEXES is not defined on WinCE. |
159 #ifndef TLS_OUT_OF_INDEXES | 159 #ifndef TLS_OUT_OF_INDEXES |
160 #define TLS_OUT_OF_INDEXES 0xffffffff | 160 #define TLS_OUT_OF_INDEXES 0xffffffff |
161 #endif | 161 #endif |
162 | 162 |
163 // The maximum number of TLS keys that can be created. For simplification, we as
sume that: | 163 // The maximum number of TLS keys that can be created. For simplification, we as
sume that: |
164 // 1) Once the instance of ThreadSpecific<> is created, it will not be destructe
d until the program dies. | 164 // 1) Once the instance of ThreadSpecific<> is created, it will not be destructe
d until the program dies. |
165 // 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed
number should be far enough. | 165 // 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed
number should be far enough. |
166 const int kMaxTlsKeySize = 256; | 166 const int kMaxTlsKeySize = 256; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 // We want get() to keep working while data destructor works, because it can
be called indirectly by the destructor. | 226 // We want get() to keep working while data destructor works, because it can
be called indirectly by the destructor. |
227 // Some pthreads implementations zero out the pointer before calling destroy
(), so we temporarily reset it. | 227 // Some pthreads implementations zero out the pointer before calling destroy
(), so we temporarily reset it. |
228 pthread_setspecific(data->owner->m_key, ptr); | 228 pthread_setspecific(data->owner->m_key, ptr); |
229 #endif | 229 #endif |
230 | 230 |
231 data->value->~T(); | 231 data->value->~T(); |
232 fastFree(data->value); | 232 fastFree(data->value); |
233 | 233 |
234 #if USE(PTHREADS) | 234 #if USE(PTHREADS) |
235 pthread_setspecific(data->owner->m_key, 0); | 235 pthread_setspecific(data->owner->m_key, 0); |
236 #elif OS(WINDOWS) | 236 #elif OS(WIN) |
237 TlsSetValue(tlsKeys()[data->owner->m_index], 0); | 237 TlsSetValue(tlsKeys()[data->owner->m_index], 0); |
238 #else | 238 #else |
239 #error ThreadSpecific is not implemented for this platform. | 239 #error ThreadSpecific is not implemented for this platform. |
240 #endif | 240 #endif |
241 | 241 |
242 delete data; | 242 delete data; |
243 } | 243 } |
244 | 244 |
245 template<typename T> | 245 template<typename T> |
246 inline bool ThreadSpecific<T>::isSet() | 246 inline bool ThreadSpecific<T>::isSet() |
(...skipping 23 matching lines...) Expand all Loading... |
270 | 270 |
271 template<typename T> | 271 template<typename T> |
272 inline T& ThreadSpecific<T>::operator*() | 272 inline T& ThreadSpecific<T>::operator*() |
273 { | 273 { |
274 return *operator T*(); | 274 return *operator T*(); |
275 } | 275 } |
276 | 276 |
277 } // namespace WTF | 277 } // namespace WTF |
278 | 278 |
279 #endif // WTF_ThreadSpecific_h | 279 #endif // WTF_ThreadSpecific_h |
OLD | NEW |