Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(266)

Side by Side Diff: third_party/WebKit/Source/wtf/ThreadSpecific.h

Issue 1611343002: wtf reformat test Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: pydent Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 detached .
62 // This is done automatically for threads created with WTF::createThread. 62 // This is done automatically for threads created with WTF::createThread.
63 WTF_EXPORT void ThreadSpecificThreadExit(); 63 WTF_EXPORT void ThreadSpecificThreadExit();
64 #endif 64 #endif
65 65
66 template<typename T> class ThreadSpecific { 66 template <typename T>
67 USING_FAST_MALLOC(ThreadSpecific); 67 class ThreadSpecific {
68 WTF_MAKE_NONCOPYABLE(ThreadSpecific); 68 USING_FAST_MALLOC(ThreadSpecific);
69 public: 69 WTF_MAKE_NONCOPYABLE(ThreadSpecific);
70 ThreadSpecific();
71 bool isSet(); // Useful as a fast check to see if this thread has set this v alue.
72 T* operator->();
73 operator T*();
74 T& operator*();
75 70
76 private: 71 public:
72 ThreadSpecific();
73 bool
74 isSet(); // Useful as a fast check to see if this thread has set this value.
75 T* operator->();
76 operator T*();
77 T& operator*();
78
79 private:
77 #if OS(WIN) 80 #if OS(WIN)
78 WTF_EXPORT friend void ThreadSpecificThreadExit(); 81 WTF_EXPORT friend void ThreadSpecificThreadExit();
79 #endif 82 #endif
80 83
81 // Not implemented. It's technically possible to destroy a thread specific k ey, but one would need 84 // Not implemented. It's technically possible to destroy a thread specific key , but one would need
82 // to make sure that all values have been destroyed already (usually, that a ll threads that used it 85 // to make sure that all values have been destroyed already (usually, that all threads that used it
83 // have exited). It's unlikely that any user of this call will be in that si tuation - and having 86 // have exited). It's unlikely that any user of this call will be in that situ ation - and having
84 // a destructor defined can be confusing, given that it has such strong pre- requisites to work correctly. 87 // a destructor defined can be confusing, given that it has such strong pre-re quisites to work correctly.
85 ~ThreadSpecific(); 88 ~ThreadSpecific();
86 89
87 T* get(); 90 T* get();
88 void set(T*); 91 void set(T*);
89 void static destroy(void* ptr); 92 void static destroy(void* ptr);
90 93
91 struct Data { 94 struct Data {
92 WTF_MAKE_NONCOPYABLE(Data); 95 WTF_MAKE_NONCOPYABLE(Data);
93 public:
94 Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {}
95 96
96 T* value; 97 public:
97 ThreadSpecific<T>* owner; 98 Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {}
99
100 T* value;
101 ThreadSpecific<T>* owner;
98 #if OS(WIN) 102 #if OS(WIN)
99 void (*destructor)(void*); 103 void (*destructor)(void*);
100 #endif 104 #endif
101 }; 105 };
102 106
103 #if OS(POSIX) 107 #if OS(POSIX)
104 pthread_key_t m_key; 108 pthread_key_t m_key;
105 #elif OS(WIN) 109 #elif OS(WIN)
106 int m_index; 110 int m_index;
107 #endif 111 #endif
108 }; 112 };
109 113
110 #if OS(POSIX) 114 #if OS(POSIX)
111 115
112 typedef pthread_key_t ThreadSpecificKey; 116 typedef pthread_key_t ThreadSpecificKey;
113 117
114 inline void threadSpecificKeyCreate(ThreadSpecificKey* key, void (*destructor)(v oid *)) 118 inline void threadSpecificKeyCreate(ThreadSpecificKey* key,
115 { 119 void (*destructor)(void*)) {
116 int error = pthread_key_create(key, destructor); 120 int error = pthread_key_create(key, destructor);
117 if (error) 121 if (error)
118 CRASH(); 122 CRASH();
119 } 123 }
120 124
121 inline void threadSpecificKeyDelete(ThreadSpecificKey key) 125 inline void threadSpecificKeyDelete(ThreadSpecificKey key) {
122 { 126 int error = pthread_key_delete(key);
123 int error = pthread_key_delete(key); 127 if (error)
124 if (error) 128 CRASH();
125 CRASH();
126 } 129 }
127 130
128 inline void threadSpecificSet(ThreadSpecificKey key, void* value) 131 inline void threadSpecificSet(ThreadSpecificKey key, void* value) {
129 { 132 pthread_setspecific(key, value);
130 pthread_setspecific(key, value);
131 } 133 }
132 134
133 inline void* threadSpecificGet(ThreadSpecificKey key) 135 inline void* threadSpecificGet(ThreadSpecificKey key) {
134 { 136 return pthread_getspecific(key);
135 return pthread_getspecific(key);
136 } 137 }
137 138
138 template<typename T> 139 template <typename T>
139 inline ThreadSpecific<T>::ThreadSpecific() 140 inline ThreadSpecific<T>::ThreadSpecific() {
140 { 141 int error = pthread_key_create(&m_key, destroy);
141 int error = pthread_key_create(&m_key, destroy); 142 if (error)
142 if (error) 143 CRASH();
143 CRASH();
144 } 144 }
145 145
146 template<typename T> 146 template <typename T>
147 inline T* ThreadSpecific<T>::get() 147 inline T* ThreadSpecific<T>::get() {
148 { 148 Data* data = static_cast<Data*>(pthread_getspecific(m_key));
149 Data* data = static_cast<Data*>(pthread_getspecific(m_key)); 149 return data ? data->value : 0;
150 return data ? data->value : 0;
151 } 150 }
152 151
153 template<typename T> 152 template <typename T>
154 inline void ThreadSpecific<T>::set(T* ptr) 153 inline void ThreadSpecific<T>::set(T* ptr) {
155 { 154 ASSERT(!get());
156 ASSERT(!get()); 155 pthread_setspecific(m_key, new Data(ptr, this));
157 pthread_setspecific(m_key, new Data(ptr, this));
158 } 156 }
159 157
160 #elif OS(WIN) 158 #elif OS(WIN)
161 159
162 // TLS_OUT_OF_INDEXES is not defined on WinCE. 160 // TLS_OUT_OF_INDEXES is not defined on WinCE.
163 #ifndef TLS_OUT_OF_INDEXES 161 #ifndef TLS_OUT_OF_INDEXES
164 #define TLS_OUT_OF_INDEXES 0xffffffff 162 #define TLS_OUT_OF_INDEXES 0xffffffff
165 #endif 163 #endif
166 164
167 // The maximum number of TLS keys that can be created. For simplification, we as sume that: 165 // The maximum number of TLS keys that can be created. For simplification, we as sume that:
168 // 1) Once the instance of ThreadSpecific<> is created, it will not be destructe d until the program dies. 166 // 1) Once the instance of ThreadSpecific<> is created, it will not be destructe d until the program dies.
169 // 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed number should be far enough. 167 // 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed number should be far enough.
170 const int kMaxTlsKeySize = 256; 168 const int kMaxTlsKeySize = 256;
171 169
172 WTF_EXPORT long& tlsKeyCount(); 170 WTF_EXPORT long& tlsKeyCount();
173 WTF_EXPORT DWORD* tlsKeys(); 171 WTF_EXPORT DWORD* tlsKeys();
174 172
175 class PlatformThreadSpecificKey; 173 class PlatformThreadSpecificKey;
176 typedef PlatformThreadSpecificKey* ThreadSpecificKey; 174 typedef PlatformThreadSpecificKey* ThreadSpecificKey;
177 175
178 WTF_EXPORT void threadSpecificKeyCreate(ThreadSpecificKey*, void (*)(void *)); 176 WTF_EXPORT void threadSpecificKeyCreate(ThreadSpecificKey*, void (*)(void*));
179 WTF_EXPORT void threadSpecificKeyDelete(ThreadSpecificKey); 177 WTF_EXPORT void threadSpecificKeyDelete(ThreadSpecificKey);
180 WTF_EXPORT void threadSpecificSet(ThreadSpecificKey, void*); 178 WTF_EXPORT void threadSpecificSet(ThreadSpecificKey, void*);
181 WTF_EXPORT void* threadSpecificGet(ThreadSpecificKey); 179 WTF_EXPORT void* threadSpecificGet(ThreadSpecificKey);
182 180
183 template<typename T> 181 template <typename T>
184 inline ThreadSpecific<T>::ThreadSpecific() 182 inline ThreadSpecific<T>::ThreadSpecific() : m_index(-1) {
185 : m_index(-1) 183 DWORD tlsKey = TlsAlloc();
186 { 184 if (tlsKey == TLS_OUT_OF_INDEXES)
187 DWORD tlsKey = TlsAlloc(); 185 CRASH();
188 if (tlsKey == TLS_OUT_OF_INDEXES)
189 CRASH();
190 186
191 m_index = InterlockedIncrement(&tlsKeyCount()) - 1; 187 m_index = InterlockedIncrement(&tlsKeyCount()) - 1;
192 if (m_index >= kMaxTlsKeySize) 188 if (m_index >= kMaxTlsKeySize)
193 CRASH(); 189 CRASH();
194 tlsKeys()[m_index] = tlsKey; 190 tlsKeys()[m_index] = tlsKey;
195 } 191 }
196 192
197 template<typename T> 193 template <typename T>
198 inline ThreadSpecific<T>::~ThreadSpecific() 194 inline ThreadSpecific<T>::~ThreadSpecific() {
199 { 195 // Does not invoke destructor functions. They will be called from ThreadSpecif icThreadExit when the thread is detached.
200 // Does not invoke destructor functions. They will be called from ThreadSpec ificThreadExit when the thread is detached. 196 TlsFree(tlsKeys()[m_index]);
201 TlsFree(tlsKeys()[m_index]);
202 } 197 }
203 198
204 template<typename T> 199 template <typename T>
205 inline T* ThreadSpecific<T>::get() 200 inline T* ThreadSpecific<T>::get() {
206 { 201 Data* data = static_cast<Data*>(TlsGetValue(tlsKeys()[m_index]));
207 Data* data = static_cast<Data*>(TlsGetValue(tlsKeys()[m_index])); 202 return data ? data->value : 0;
208 return data ? data->value : 0;
209 } 203 }
210 204
211 template<typename T> 205 template <typename T>
212 inline void ThreadSpecific<T>::set(T* ptr) 206 inline void ThreadSpecific<T>::set(T* ptr) {
213 { 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);
218 } 211 }
219 212
220 #else 213 #else
221 #error ThreadSpecific is not implemented for this platform. 214 #error ThreadSpecific is not implemented for this platform.
222 #endif 215 #endif
223 216
224 template<typename T> 217 template <typename T>
225 inline void ThreadSpecific<T>::destroy(void* ptr) 218 inline void ThreadSpecific<T>::destroy(void* ptr) {
226 { 219 if (isShutdown())
227 if (isShutdown()) 220 return;
228 return;
229 221
230 Data* data = static_cast<Data*>(ptr); 222 Data* data = static_cast<Data*>(ptr);
231 223
232 #if OS(POSIX) 224 #if OS(POSIX)
233 // We want get() to keep working while data destructor works, because it can be called indirectly by the destructor. 225 // We want get() to keep working while data destructor works, because it can b e called indirectly by the destructor.
234 // Some pthreads implementations zero out the pointer before calling destroy (), so we temporarily reset it. 226 // Some pthreads implementations zero out the pointer before calling destroy() , so we temporarily reset it.
235 pthread_setspecific(data->owner->m_key, ptr); 227 pthread_setspecific(data->owner->m_key, ptr);
236 #endif 228 #endif
237 229
238 data->value->~T(); 230 data->value->~T();
239 Partitions::fastFree(data->value); 231 Partitions::fastFree(data->value);
240 232
241 #if OS(POSIX) 233 #if OS(POSIX)
242 pthread_setspecific(data->owner->m_key, 0); 234 pthread_setspecific(data->owner->m_key, 0);
243 #elif OS(WIN) 235 #elif OS(WIN)
244 TlsSetValue(tlsKeys()[data->owner->m_index], 0); 236 TlsSetValue(tlsKeys()[data->owner->m_index], 0);
245 #else 237 #else
246 #error ThreadSpecific is not implemented for this platform. 238 #error ThreadSpecific is not implemented for this platform.
247 #endif 239 #endif
248 240
249 delete data; 241 delete data;
250 } 242 }
251 243
252 template<typename T> 244 template <typename T>
253 inline bool ThreadSpecific<T>::isSet() 245 inline bool ThreadSpecific<T>::isSet() {
254 { 246 return !!get();
255 return !!get();
256 } 247 }
257 248
258 template<typename T> 249 template <typename T>
259 inline ThreadSpecific<T>::operator T*() 250 inline ThreadSpecific<T>::operator T*() {
260 { 251 T* ptr = static_cast<T*>(get());
261 T* ptr = static_cast<T*>(get()); 252 if (!ptr) {
262 if (!ptr) { 253 // Set up thread-specific value's memory pointer before invoking constructor , in case any function it calls
263 // Set up thread-specific value's memory pointer before invoking constru ctor, in case any function it calls 254 // needs to access the value, to avoid recursion.
264 // needs to access the value, to avoid recursion. 255 ptr = static_cast<T*>(Partitions::fastZeroedMalloc(
265 ptr = static_cast<T*>(Partitions::fastZeroedMalloc(sizeof(T), WTF_HEAP_P ROFILER_TYPE_NAME(T))); 256 sizeof(T), WTF_HEAP_PROFILER_TYPE_NAME(T)));
266 set(ptr); 257 set(ptr);
267 new (NotNull, ptr) T; 258 new (NotNull, ptr) T;
268 } 259 }
269 return ptr; 260 return ptr;
270 } 261 }
271 262
272 template<typename T> 263 template <typename T>
273 inline T* ThreadSpecific<T>::operator->() 264 inline T* ThreadSpecific<T>::operator->() {
274 { 265 return operator T*();
275 return operator T*();
276 } 266 }
277 267
278 template<typename T> 268 template <typename T>
279 inline T& ThreadSpecific<T>::operator*() 269 inline T& ThreadSpecific<T>::operator*() {
280 { 270 return *operator T*();
281 return *operator T*();
282 } 271 }
283 272
284 } // namespace WTF 273 } // namespace WTF
285 274
286 using WTF::ThreadSpecific; 275 using WTF::ThreadSpecific;
287 276
288 #endif // WTF_ThreadSpecific_h 277 #endif // WTF_ThreadSpecific_h
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/ThreadSafeRefCounted.h ('k') | third_party/WebKit/Source/wtf/ThreadSpecificWin.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698