diff options
Diffstat (limited to 'Source/WTF/wtf/ThreadSpecificWin.cpp')
-rw-r--r-- | Source/WTF/wtf/ThreadSpecificWin.cpp | 90 |
1 files changed, 86 insertions, 4 deletions
diff --git a/Source/WTF/wtf/ThreadSpecificWin.cpp b/Source/WTF/wtf/ThreadSpecificWin.cpp index d72996a7a..61a594251 100644 --- a/Source/WTF/wtf/ThreadSpecificWin.cpp +++ b/Source/WTF/wtf/ThreadSpecificWin.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 Jian Li <jianli@chromium.org> + * Copyright (C) 2012 Patrick Gansterer <paroga@paroga.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -19,15 +20,72 @@ */ #include "config.h" - #include "ThreadSpecific.h" -#if USE(PTHREADS) -#error This file should not be compiled by ports that do not use Windows native ThreadSpecific implementation. -#endif +#include "StdLibExtras.h" +#include "ThreadingPrimitives.h" + +#if !USE(PTHREADS) namespace WTF { +static Mutex& destructorsMutex() +{ + DEFINE_STATIC_LOCAL(Mutex, staticMutex, ()); + return staticMutex; +} + +class ThreadSpecificKeyValue { +public: + ThreadSpecificKeyValue(void (*destructor)(void *)) + : m_destructor(destructor) + { + m_tlsKey = TlsAlloc(); + if (m_tlsKey == TLS_OUT_OF_INDEXES) + CRASH(); + + MutexLocker locker(destructorsMutex()); + m_next = m_first; + m_first = this; + } + + ~ThreadSpecificKeyValue() + { + MutexLocker locker(destructorsMutex()); + ThreadSpecificKeyValue** next = &m_first; + while (*next != this) { + ASSERT(*next); + next = &(*next)->m_next; + } + *next = (*next)->m_next; + + TlsFree(m_tlsKey); + } + + void setValue(void* data) { TlsSetValue(m_tlsKey, data); } + void* value() { return TlsGetValue(m_tlsKey); } + + static void callDestructors() + { + MutexLocker locker(destructorsMutex()); + ThreadSpecificKeyValue* next = m_first; + while (next) { + if (void* data = next->value()) + next->m_destructor(data); + next = next->m_next; + } + } + +private: + void (*m_destructor)(void *); + DWORD m_tlsKey; + ThreadSpecificKeyValue* m_next; + + static ThreadSpecificKeyValue* m_first; +}; + +ThreadSpecificKeyValue* ThreadSpecificKeyValue::m_first = 0; + long& tlsKeyCount() { static long count; @@ -40,6 +98,26 @@ DWORD* tlsKeys() return keys; } +void ThreadSpecificKeyCreate(ThreadSpecificKey* key, void (*destructor)(void *)) +{ + *key = new ThreadSpecificKeyValue(destructor); +} + +void ThreadSpecificKeyDelete(ThreadSpecificKey key) +{ + delete key; +} + +void ThreadSpecificSet(ThreadSpecificKey key, void* data) +{ + key->setValue(data); +} + +void* ThreadSpecificGet(ThreadSpecificKey key) +{ + return key->value(); +} + void ThreadSpecificThreadExit() { for (long i = 0; i < tlsKeyCount(); i++) { @@ -48,6 +126,10 @@ void ThreadSpecificThreadExit() if (data) data->destructor(data); } + + ThreadSpecificKeyValue::callDestructors(); } } // namespace WTF + +#endif // !USE(PTHREADS) |