Changeset 39708 in webkit for trunk/JavaScriptCore/wtf/ThreadSpecific.h
- Timestamp:
- Jan 8, 2009, 8:47:14 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/wtf/ThreadSpecific.h
r39672 r39708 1 1 /* 2 2 * Copyright (C) 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2009 Jian Li <[email protected]> 3 4 * 4 5 * Redistribution and use in source and binary forms, with or without … … 27 28 */ 28 29 30 /* Thread local storage is implemented by using either pthread API or Windows 31 * native API. There is subtle semantic discrepancy for the cleanup function 32 * implementation as noted below: 33 * @ In pthread implementation, the destructor function will be called 34 * repeatedly if there is still non-NULL value associated with the function. 35 * @ In Windows native implementation, the destructor function will be called 36 * only once. 37 * This semantic discrepancy does not impose any problem because nowhere in 38 * WebKit the repeated call bahavior is utilized. 39 */ 40 29 41 #ifndef WTF_ThreadSpecific_h 30 42 #define WTF_ThreadSpecific_h … … 32 44 #include <wtf/Noncopyable.h> 33 45 34 #if USE(PTHREADS) || PLATFORM(WIN) 35 // Windows currently doesn't use pthreads for basic threading, but implementing destructor functions is easier 36 // with pthreads, so we use it here. 46 #if USE(PTHREADS) 37 47 #include <pthread.h> 48 #elif PLATFORM(WIN_OS) 49 #include <windows.h> 38 50 #endif 39 51 40 52 namespace WTF { 53 54 #if !USE(PTHREADS) && PLATFORM(WIN_OS) 55 // ThreadSpecificThreadExit should be called each time when a thread is detached. 56 // This is done automatically for threads created with WTF::createThread. 57 void ThreadSpecificThreadExit(); 58 #endif 41 59 42 60 template<typename T> class ThreadSpecific : Noncopyable { … … 49 67 50 68 private: 69 #if !USE(PTHREADS) && PLATFORM(WIN_OS) 70 friend void ThreadSpecificThreadExit(); 71 #endif 72 51 73 T* get(); 52 74 void set(T*); 53 75 void static destroy(void* ptr); 54 76 55 #if USE(PTHREADS) || PLATFORM(WIN )77 #if USE(PTHREADS) || PLATFORM(WIN_OS) 56 78 struct Data : Noncopyable { 57 79 Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {} … … 59 81 T* value; 60 82 ThreadSpecific<T>* owner; 83 #if !USE(PTHREADS) 84 void (*destructor)(void*); 85 #endif 61 86 }; 62 87 #endif 88 89 #if USE(PTHREADS) 63 90 pthread_key_t m_key; 91 #elif PLATFORM(WIN_OS) 92 int m_index; 64 93 #endif 65 94 }; 66 95 67 #if USE(PTHREADS) || PLATFORM(WIN)96 #if USE(PTHREADS) 68 97 template<typename T> 69 98 inline ThreadSpecific<T>::ThreadSpecific() … … 94 123 } 95 124 125 #elif PLATFORM(WIN_OS) 126 127 // The maximum number of TLS keys that can be created. For simplification, we assume that: 128 // 1) Once the instance of ThreadSpecific<> is created, it will not be destructed until the program dies. 129 // 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed number should be far enough. 130 const int kMaxTlsKeySize = 256; 131 132 extern long g_tls_key_count; 133 extern DWORD g_tls_keys[kMaxTlsKeySize]; 134 135 template<typename T> 136 inline ThreadSpecific<T>::ThreadSpecific() 137 : m_index(-1) 138 { 139 DWORD tls_key = TlsAlloc(); 140 if (tls_key == TLS_OUT_OF_INDEXES) 141 CRASH(); 142 143 m_index = InterlockedIncrement(&g_tls_key_count) - 1; 144 if (m_index >= kMaxTlsKeySize) 145 CRASH(); 146 g_tls_keys[m_index] = tls_key; 147 } 148 149 template<typename T> 150 inline ThreadSpecific<T>::~ThreadSpecific() 151 { 152 // Does not invoke destructor functions. They will be called from ThreadSpecificThreadExit when the thread is detached. 153 TlsFree(g_tls_keys[m_index]); 154 } 155 156 template<typename T> 157 inline T* ThreadSpecific<T>::get() 158 { 159 Data* data = static_cast<Data*>(TlsGetValue(g_tls_keys[m_index])); 160 return data ? data->value : 0; 161 } 162 163 template<typename T> 164 inline void ThreadSpecific<T>::set(T* ptr) 165 { 166 ASSERT(!get()); 167 Data* data = new Data(ptr, this); 168 data->destructor = &ThreadSpecific<T>::destroy; 169 TlsSetValue(g_tls_keys[m_index], data); 170 } 171 172 #else 173 #error ThreadSpecific is not implemented for this platform. 174 #endif 175 96 176 template<typename T> 97 177 inline void ThreadSpecific<T>::destroy(void* ptr) … … 99 179 Data* data = static_cast<Data*>(ptr); 100 180 181 #if USE(PTHREADS) 101 182 // We want get() to keep working while data destructor works, because it can be called indirectly by the destructor. 102 183 // Some pthreads implementations zero out the pointer before calling destroy(), so we temporarily reset it. 103 184 pthread_setspecific(data->owner->m_key, ptr); 185 #endif 186 104 187 data->value->~T(); 105 188 fastFree(data->value); 189 190 #if USE(PTHREADS) 106 191 pthread_setspecific(data->owner->m_key, 0); 107 delete data; 108 } 109 192 #elif PLATFORM(WIN_OS) 193 TlsSetValue(g_tls_keys[data->owner->m_index], 0); 110 194 #else 111 195 #error ThreadSpecific is not implemented for this platform. 112 196 #endif 197 198 delete data; 199 } 113 200 114 201 template<typename T>
Note:
See TracChangeset
for help on using the changeset viewer.