]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - wtf/ThreadSpecific.h
JavaScriptCore-721.26.tar.gz
[apple/javascriptcore.git] / wtf / ThreadSpecific.h
index 76038025d9340fd68c88350ed47b362979371851..7e5679f9649ffcef42ebaa7e9779c8383f329fc8 100644 (file)
 
 #if USE(PTHREADS)
 #include <pthread.h>
-#elif PLATFORM(WIN_OS)
+#elif PLATFORM(QT)
+#include <QThreadStorage>
+#elif OS(WINDOWS)
 #include <windows.h>
 #endif
 
 namespace WTF {
 
-#if !USE(PTHREADS) && PLATFORM(WIN_OS)
+#if !USE(PTHREADS) && !PLATFORM(QT) && OS(WINDOWS)
 // ThreadSpecificThreadExit should be called each time when a thread is detached.
 // This is done automatically for threads created with WTF::createThread.
 void ThreadSpecificThreadExit();
 #endif
 
-template<typename T> class ThreadSpecific : Noncopyable {
+template<typename T> class ThreadSpecific : public Noncopyable {
 public:
     ThreadSpecific();
     T* operator->();
@@ -66,7 +68,7 @@ public:
     ~ThreadSpecific();
 
 private:
-#if !USE(PTHREADS) && PLATFORM(WIN_OS)
+#if !USE(PTHREADS) && !PLATFORM(QT) && OS(WINDOWS)
     friend void ThreadSpecificThreadExit();
 #endif
     
@@ -74,25 +76,59 @@ private:
     void set(T*);
     void static destroy(void* ptr);
 
-#if USE(PTHREADS) || PLATFORM(WIN_OS)
+#if USE(PTHREADS) || PLATFORM(QT) || OS(WINDOWS)
     struct Data : Noncopyable {
         Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {}
+#if PLATFORM(QT)
+        ~Data() { owner->destroy(this); }
+#endif
 
         T* value;
         ThreadSpecific<T>* owner;
-#if !USE(PTHREADS)
+#if !USE(PTHREADS) && !PLATFORM(QT)
         void (*destructor)(void*);
 #endif
     };
 #endif
 
+#if ENABLE(SINGLE_THREADED)
+    T* m_value;
+#else
 #if USE(PTHREADS)
     pthread_key_t m_key;
-#elif PLATFORM(WIN_OS)
+#elif PLATFORM(QT)
+    QThreadStorage<Data*> m_key;
+#elif OS(WINDOWS)
     int m_index;
 #endif
+#endif
 };
 
+#if ENABLE(SINGLE_THREADED)
+template<typename T>
+inline ThreadSpecific<T>::ThreadSpecific()
+    : m_value(0)
+{
+}
+
+template<typename T>
+inline ThreadSpecific<T>::~ThreadSpecific()
+{
+}
+
+template<typename T>
+inline T* ThreadSpecific<T>::get()
+{
+    return m_value;
+}
+
+template<typename T>
+inline void ThreadSpecific<T>::set(T* ptr)
+{
+    ASSERT(!get());
+    m_value = ptr;
+}
+#else
 #if USE(PTHREADS)
 template<typename T>
 inline ThreadSpecific<T>::ThreadSpecific()
@@ -122,41 +158,74 @@ inline void ThreadSpecific<T>::set(T* ptr)
     pthread_setspecific(m_key, new Data(ptr, this));
 }
 
-#elif PLATFORM(WIN_OS)
+#elif PLATFORM(QT)
+
+template<typename T>
+inline ThreadSpecific<T>::ThreadSpecific()
+{
+}
+
+template<typename T>
+inline ThreadSpecific<T>::~ThreadSpecific()
+{
+    // Does not invoke destructor functions. QThreadStorage will do it
+}
+
+template<typename T>
+inline T* ThreadSpecific<T>::get()
+{
+    Data* data = static_cast<Data*>(m_key.localData());
+    return data ? data->value : 0;
+}
+
+template<typename T>
+inline void ThreadSpecific<T>::set(T* ptr)
+{
+    ASSERT(!get());
+    Data* data = new Data(ptr, this);
+    m_key.setLocalData(data);
+}
+
+#elif OS(WINDOWS)
+
+// TLS_OUT_OF_INDEXES is not defined on WinCE.
+#ifndef TLS_OUT_OF_INDEXES
+#define TLS_OUT_OF_INDEXES 0xffffffff
+#endif
 
 // The maximum number of TLS keys that can be created. For simplification, we assume that:
 // 1) Once the instance of ThreadSpecific<> is created, it will not be destructed until the program dies.
 // 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed number should be far enough.
 const int kMaxTlsKeySize = 256;
 
-extern long g_tls_key_count;
-extern DWORD g_tls_keys[kMaxTlsKeySize];
+long& tlsKeyCount();
+DWORD* tlsKeys();
 
 template<typename T>
 inline ThreadSpecific<T>::ThreadSpecific()
     : m_index(-1)
 {
-    DWORD tls_key = TlsAlloc();
-    if (tls_key == TLS_OUT_OF_INDEXES)
+    DWORD tlsKey = TlsAlloc();
+    if (tlsKey == TLS_OUT_OF_INDEXES)
         CRASH();
 
-    m_index = InterlockedIncrement(&g_tls_key_count) - 1;
+    m_index = InterlockedIncrement(&tlsKeyCount()) - 1;
     if (m_index >= kMaxTlsKeySize)
         CRASH();
-    g_tls_keys[m_index] = tls_key;
+    tlsKeys()[m_index] = tlsKey;
 }
 
 template<typename T>
 inline ThreadSpecific<T>::~ThreadSpecific()
 {
     // Does not invoke destructor functions. They will be called from ThreadSpecificThreadExit when the thread is detached.
-    TlsFree(g_tls_keys[m_index]);
+    TlsFree(tlsKeys()[m_index]);
 }
 
 template<typename T>
 inline T* ThreadSpecific<T>::get()
 {
-    Data* data = static_cast<Data*>(TlsGetValue(g_tls_keys[m_index]));
+    Data* data = static_cast<Data*>(TlsGetValue(tlsKeys()[m_index]));
     return data ? data->value : 0;
 }
 
@@ -166,16 +235,18 @@ inline void ThreadSpecific<T>::set(T* ptr)
     ASSERT(!get());
     Data* data = new Data(ptr, this);
     data->destructor = &ThreadSpecific<T>::destroy;
-    TlsSetValue(g_tls_keys[m_index], data);
+    TlsSetValue(tlsKeys()[m_index], data);
 }
 
 #else
 #error ThreadSpecific is not implemented for this platform.
 #endif
+#endif
 
 template<typename T>
 inline void ThreadSpecific<T>::destroy(void* ptr)
 {
+#if !ENABLE(SINGLE_THREADED)
     Data* data = static_cast<Data*>(ptr);
 
 #if USE(PTHREADS)
@@ -183,19 +254,28 @@ inline void ThreadSpecific<T>::destroy(void* ptr)
     // Some pthreads implementations zero out the pointer before calling destroy(), so we temporarily reset it.
     pthread_setspecific(data->owner->m_key, ptr);
 #endif
-    
+#if PLATFORM(QT)
+    // See comment as above
+    data->owner->m_key.setLocalData(data);
+#endif
+
     data->value->~T();
     fastFree(data->value);
 
 #if USE(PTHREADS)
     pthread_setspecific(data->owner->m_key, 0);
-#elif PLATFORM(WIN_OS)
-    TlsSetValue(g_tls_keys[data->owner->m_index], 0);
+#elif PLATFORM(QT)
+    // Do nothing here
+#elif OS(WINDOWS)
+    TlsSetValue(tlsKeys()[data->owner->m_index], 0);
 #else
 #error ThreadSpecific is not implemented for this platform.
 #endif
 
+#if !PLATFORM(QT)
     delete data;
+#endif
+#endif
 }
 
 template<typename T>