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

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

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