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

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

Issue 1849023002: WTF::ThreadSpecific should use base::ThreadLocalStorage. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Check isShutdown(). Created 4 years, 8 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
« no previous file with comments | « third_party/WebKit/Source/wtf/DEPS ('k') | third_party/WebKit/Source/wtf/ThreadSpecificWin.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 24 matching lines...) Expand all
35 * repeatedly if there is still non-NULL value associated with the function. 35 * repeatedly if there is still non-NULL value associated with the function.
36 * @ In Windows native implementation, the destructor function will be called 36 * @ In Windows native implementation, the destructor function will be called
37 * only once. 37 * only once.
38 * This semantic discrepancy does not impose any problem because nowhere in 38 * This semantic discrepancy does not impose any problem because nowhere in
39 * WebKit the repeated call bahavior is utilized. 39 * WebKit the repeated call bahavior is utilized.
40 */ 40 */
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 "base/threading/thread_local_storage.h"
45 #include "wtf/Allocator.h" 46 #include "wtf/Allocator.h"
46 #include "wtf/Noncopyable.h" 47 #include "wtf/Noncopyable.h"
47 #include "wtf/Partitions.h" 48 #include "wtf/Partitions.h"
48 #include "wtf/StdLibExtras.h"
49 #include "wtf/WTF.h" 49 #include "wtf/WTF.h"
50 #include "wtf/WTFExport.h"
51
52 #if OS(POSIX)
53 #include <pthread.h>
54 #elif OS(WIN)
55 #include <windows.h>
56 #endif
57 50
58 namespace WTF { 51 namespace WTF {
59 52
60 #if OS(WIN) 53 template<typename T>
61 // ThreadSpecificThreadExit should be called each time when a thread is detached . 54 class ThreadSpecific {
62 // This is done automatically for threads created with WTF::createThread.
63 WTF_EXPORT void ThreadSpecificThreadExit();
64 #endif
65
66 template<typename T> class ThreadSpecific {
67 USING_FAST_MALLOC(ThreadSpecific); 55 USING_FAST_MALLOC(ThreadSpecific);
68 WTF_MAKE_NONCOPYABLE(ThreadSpecific); 56 WTF_MAKE_NONCOPYABLE(ThreadSpecific);
69 public: 57 public:
70 ThreadSpecific(); 58 ThreadSpecific()
71 bool isSet(); // Useful as a fast check to see if this thread has set this v alue. 59 : m_slot(&destory)
72 T* operator->(); 60 { }
73 operator T*(); 61
74 T& operator*(); 62 operator T*() { return get(); }
63 T* operator->() { return get(); }
64 T& operator*() { return *get(); }
75 65
76 private: 66 private:
77 #if OS(WIN)
78 WTF_EXPORT friend void ThreadSpecificThreadExit();
79 #endif
80
81 // Not implemented. It's technically possible to destroy a thread specific k ey, but one would need 67 // Not implemented. It's technically possible to destroy a thread specific k ey, but one would need
82 // to make sure that all values have been destroyed already (usually, that a ll threads that used it 68 // to make sure that all values have been destroyed already (usually, that a ll threads that used it
83 // have exited). It's unlikely that any user of this call will be in that si tuation - and having 69 // have exited). It's unlikely that any user of this call will be in that si tuation - and having
84 // a destructor defined can be confusing, given that it has such strong pre- requisites to work correctly. 70 // a destructor defined can be confusing, given that it has such strong pre- requisites to work correctly.
85 ~ThreadSpecific(); 71 ~ThreadSpecific();
86 72
87 T* get(); 73 T* get()
88 void set(T*); 74 {
89 void static destroy(void* ptr); 75 T* ptr = static_cast<T*>(m_slot.Get());
76 if (!ptr) {
77 // Set up thread-specific value's memory pointer before invoking con structor, in case any function it calls
78 // needs to access the value, to avoid recursion.
79 ptr = static_cast<T*>(Partitions::fastZeroedMalloc(sizeof(T), WTF_HE AP_PROFILER_TYPE_NAME(T)));
80 m_slot.Set(ptr);
81 new (NotNull, ptr) T;
82 }
83 return ptr;
84 }
90 85
91 struct Data { 86 static void destory(void* value)
92 WTF_MAKE_NONCOPYABLE(Data); 87 {
93 public: 88 if (isShutdown())
haraken 2016/04/01 12:28:35 I'm not sure if this check is needed though.
94 Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {} 89 return;
90 T* ptr = static_cast<T*>(value);
91 ptr->~T();
92 Partitions::fastFree(ptr);
93 }
95 94
96 T* value; 95 base::ThreadLocalStorage::Slot m_slot;
97 ThreadSpecific<T>* owner;
98 #if OS(WIN)
99 void (*destructor)(void*);
100 #endif
101 };
102
103 #if OS(POSIX)
104 pthread_key_t m_key;
105 #elif OS(WIN)
106 int m_index;
107 #endif
108 }; 96 };
109 97
110 #if OS(POSIX)
111
112 typedef pthread_key_t ThreadSpecificKey;
113
114 inline void threadSpecificKeyCreate(ThreadSpecificKey* key, void (*destructor)(v oid *))
115 {
116 int error = pthread_key_create(key, destructor);
117 if (error)
118 CRASH();
119 }
120
121 inline void threadSpecificKeyDelete(ThreadSpecificKey key)
122 {
123 int error = pthread_key_delete(key);
124 if (error)
125 CRASH();
126 }
127
128 inline void threadSpecificSet(ThreadSpecificKey key, void* value)
129 {
130 pthread_setspecific(key, value);
131 }
132
133 inline void* threadSpecificGet(ThreadSpecificKey key)
134 {
135 return pthread_getspecific(key);
136 }
137
138 template<typename T>
139 inline ThreadSpecific<T>::ThreadSpecific()
140 {
141 int error = pthread_key_create(&m_key, destroy);
142 if (error)
143 CRASH();
144 }
145
146 template<typename T>
147 inline T* ThreadSpecific<T>::get()
148 {
149 Data* data = static_cast<Data*>(pthread_getspecific(m_key));
150 return data ? data->value : 0;
151 }
152
153 template<typename T>
154 inline void ThreadSpecific<T>::set(T* ptr)
155 {
156 ASSERT(!get());
157 pthread_setspecific(m_key, new Data(ptr, this));
158 }
159
160 #elif OS(WIN)
161
162 // TLS_OUT_OF_INDEXES is not defined on WinCE.
163 #ifndef TLS_OUT_OF_INDEXES
164 #define TLS_OUT_OF_INDEXES 0xffffffff
165 #endif
166
167 // 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.
169 // 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed number should be far enough.
170 const int kMaxTlsKeySize = 256;
171
172 WTF_EXPORT long& tlsKeyCount();
173 WTF_EXPORT DWORD* tlsKeys();
174
175 class PlatformThreadSpecificKey;
176 typedef PlatformThreadSpecificKey* ThreadSpecificKey;
177
178 WTF_EXPORT void threadSpecificKeyCreate(ThreadSpecificKey*, void (*)(void *));
179 WTF_EXPORT void threadSpecificKeyDelete(ThreadSpecificKey);
180 WTF_EXPORT void threadSpecificSet(ThreadSpecificKey, void*);
181 WTF_EXPORT void* threadSpecificGet(ThreadSpecificKey);
182
183 template<typename T>
184 inline ThreadSpecific<T>::ThreadSpecific()
185 : m_index(-1)
186 {
187 DWORD tlsKey = TlsAlloc();
188 if (tlsKey == TLS_OUT_OF_INDEXES)
189 CRASH();
190
191 m_index = InterlockedIncrement(&tlsKeyCount()) - 1;
192 if (m_index >= kMaxTlsKeySize)
193 CRASH();
194 tlsKeys()[m_index] = tlsKey;
195 }
196
197 template<typename T>
198 inline ThreadSpecific<T>::~ThreadSpecific()
199 {
200 // Does not invoke destructor functions. They will be called from ThreadSpec ificThreadExit when the thread is detached.
201 TlsFree(tlsKeys()[m_index]);
202 }
203
204 template<typename T>
205 inline T* ThreadSpecific<T>::get()
206 {
207 Data* data = static_cast<Data*>(TlsGetValue(tlsKeys()[m_index]));
208 return data ? data->value : 0;
209 }
210
211 template<typename T>
212 inline void ThreadSpecific<T>::set(T* ptr)
213 {
214 ASSERT(!get());
215 Data* data = new Data(ptr, this);
216 data->destructor = &ThreadSpecific<T>::destroy;
217 TlsSetValue(tlsKeys()[m_index], data);
218 }
219
220 #else
221 #error ThreadSpecific is not implemented for this platform.
222 #endif
223
224 template<typename T>
225 inline void ThreadSpecific<T>::destroy(void* ptr)
226 {
227 if (isShutdown())
228 return;
229
230 Data* data = static_cast<Data*>(ptr);
231
232 #if OS(POSIX)
233 // We want get() to keep working while data destructor works, because it can be called indirectly by the destructor.
234 // Some pthreads implementations zero out the pointer before calling destroy (), so we temporarily reset it.
235 pthread_setspecific(data->owner->m_key, ptr);
236 #endif
237
238 data->value->~T();
239 Partitions::fastFree(data->value);
240
241 #if OS(POSIX)
242 pthread_setspecific(data->owner->m_key, 0);
243 #elif OS(WIN)
244 TlsSetValue(tlsKeys()[data->owner->m_index], 0);
245 #else
246 #error ThreadSpecific is not implemented for this platform.
247 #endif
248
249 delete data;
250 }
251
252 template<typename T>
253 inline bool ThreadSpecific<T>::isSet()
254 {
255 return !!get();
256 }
257
258 template<typename T>
259 inline ThreadSpecific<T>::operator T*()
260 {
261 T* ptr = static_cast<T*>(get());
262 if (!ptr) {
263 // Set up thread-specific value's memory pointer before invoking constru ctor, in case any function it calls
264 // needs to access the value, to avoid recursion.
265 ptr = static_cast<T*>(Partitions::fastZeroedMalloc(sizeof(T), WTF_HEAP_P ROFILER_TYPE_NAME(T)));
266 set(ptr);
267 new (NotNull, ptr) T;
268 }
269 return ptr;
270 }
271
272 template<typename T>
273 inline T* ThreadSpecific<T>::operator->()
274 {
275 return operator T*();
276 }
277
278 template<typename T>
279 inline T& ThreadSpecific<T>::operator*()
280 {
281 return *operator T*();
282 }
283
284 } // namespace WTF 98 } // namespace WTF
285 99
286 using WTF::ThreadSpecific; 100 using WTF::ThreadSpecific;
287 101
288 #endif // WTF_ThreadSpecific_h 102 #endif // WTF_ThreadSpecific_h
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/DEPS ('k') | third_party/WebKit/Source/wtf/ThreadSpecificWin.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698