#include <pthread.h>
#elif PLATFORM(QT)
#include <QThreadStorage>
-#elif PLATFORM(WIN_OS)
+#elif OS(WINDOWS)
#include <windows.h>
#endif
namespace WTF {
-#if !USE(PTHREADS) && !PLATFORM(QT) && 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->();
~ThreadSpecific();
private:
-#if !USE(PTHREADS) && !PLATFORM(QT) && PLATFORM(WIN_OS)
+#if !USE(PTHREADS) && !PLATFORM(QT) && OS(WINDOWS)
friend void ThreadSpecificThreadExit();
#endif
void set(T*);
void static destroy(void* ptr);
-#if USE(PTHREADS) || PLATFORM(QT) || 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(QT)
QThreadStorage<Data*> m_key;
-#elif PLATFORM(WIN_OS)
+#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()
template<typename T>
inline ThreadSpecific<T>::~ThreadSpecific()
{
- Data* data = static_cast<Data*>(m_key.localData());
- if (data)
- data->destructor(data);
+ // Does not invoke destructor functions. QThreadStorage will do it
}
template<typename T>
{
ASSERT(!get());
Data* data = new Data(ptr, this);
- data->destructor = &ThreadSpecific<T>::destroy;
m_key.setLocalData(data);
}
-#elif PLATFORM(WIN_OS)
+#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.
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(&tlsKeyCount()) - 1;
if (m_index >= kMaxTlsKeySize)
CRASH();
- tlsKeys()[m_index] = tls_key;
+ tlsKeys()[m_index] = tlsKey;
}
template<typename T>
#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)
// 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(QT)
- data->owner->m_key.setLocalData(0);
-#elif PLATFORM(WIN_OS)
+ // 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>