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

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

Issue 1856793002: Revert of WTF::ThreadSpecific should use base::ThreadLocalStorage. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Manual revert 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"
46 #include "wtf/Allocator.h" 45 #include "wtf/Allocator.h"
47 #include "wtf/Noncopyable.h" 46 #include "wtf/Noncopyable.h"
48 #include "wtf/Partitions.h" 47 #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
50 57
51 namespace WTF { 58 namespace WTF {
52 59
53 template<typename T> 60 #if OS(WIN)
54 class ThreadSpecific { 61 // ThreadSpecificThreadExit should be called each time when a thread is detached .
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 {
55 USING_FAST_MALLOC(ThreadSpecific); 67 USING_FAST_MALLOC(ThreadSpecific);
56 WTF_MAKE_NONCOPYABLE(ThreadSpecific); 68 WTF_MAKE_NONCOPYABLE(ThreadSpecific);
57 public: 69 public:
58 ThreadSpecific() 70 ThreadSpecific();
59 : m_slot(&destory) 71 bool isSet(); // Useful as a fast check to see if this thread has set this v alue.
60 { } 72 T* operator->();
61 73 operator T*();
62 operator T*() { return get(); } 74 T& operator*();
63 T* operator->() { return get(); }
64 T& operator*() { return *get(); }
65 75
66 private: 76 private:
77 #if OS(WIN)
78 WTF_EXPORT friend void ThreadSpecificThreadExit();
79 #endif
80
67 // 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 k ey, but one would need
68 // 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 a ll threads that used it
69 // 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 si tuation - and having
70 // 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- requisites to work correctly.
71 ~ThreadSpecific(); 85 ~ThreadSpecific();
72 86
73 T* get() 87 T* get();
74 { 88 void set(T*);
75 T* ptr = static_cast<T*>(m_slot.Get()); 89 void static destroy(void* ptr);
76 if (!ptr) { 90
77 // Set up thread-specific value's memory pointer before invoking con structor, in case any function it calls 91 struct Data {
78 // needs to access the value, to avoid recursion. 92 WTF_MAKE_NONCOPYABLE(Data);
79 ptr = static_cast<T*>(Partitions::fastZeroedMalloc(sizeof(T), WTF_HE AP_PROFILER_TYPE_NAME(T))); 93 public:
80 m_slot.Set(ptr); 94 Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {}
81 new (NotNull, ptr) T; 95
82 } 96 T* value;
83 return ptr; 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 };
109
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;
84 } 268 }
85 269 return ptr;
86 static void destory(void* value) 270 }
87 { 271
88 if (isShutdown()) 272 template<typename T>
89 return; 273 inline T* ThreadSpecific<T>::operator->()
90 T* ptr = static_cast<T*>(value); 274 {
91 ptr->~T(); 275 return operator T*();
92 Partitions::fastFree(ptr); 276 }
93 } 277
94 278 template<typename T>
95 base::ThreadLocalStorage::Slot m_slot; 279 inline T& ThreadSpecific<T>::operator*()
96 }; 280 {
281 return *operator T*();
282 }
97 283
98 } // namespace WTF 284 } // namespace WTF
99 285
100 using WTF::ThreadSpecific; 286 using WTF::ThreadSpecific;
101 287
102 #endif // WTF_ThreadSpecific_h 288 #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