X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/1df5f87f1309a8daa30dabdee855f48ae40d14ab..6fe7ccc865dc7d7541b93c5bcaf6368d2c98a174:/wtf/ThreadSpecific.h?ds=inline diff --git a/wtf/ThreadSpecific.h b/wtf/ThreadSpecific.h deleted file mode 100644 index 0aeee13..0000000 --- a/wtf/ThreadSpecific.h +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * Copyright (C) 2009 Jian Li - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* Thread local storage is implemented by using either pthread API or Windows - * native API. There is subtle semantic discrepancy for the cleanup function - * implementation as noted below: - * @ In pthread implementation, the destructor function will be called - * repeatedly if there is still non-NULL value associated with the function. - * @ In Windows native implementation, the destructor function will be called - * only once. - * This semantic discrepancy does not impose any problem because nowhere in - * WebKit the repeated call bahavior is utilized. - */ - -#ifndef WTF_ThreadSpecific_h -#define WTF_ThreadSpecific_h - -#include - -#if USE(PTHREADS) -#include -#elif PLATFORM(QT) -#include -#elif PLATFORM(GTK) -#include -#elif OS(WINDOWS) -#include -#endif - -namespace WTF { - -#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK) && 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 class ThreadSpecific { - WTF_MAKE_NONCOPYABLE(ThreadSpecific); -public: - ThreadSpecific(); - T* operator->(); - operator T*(); - T& operator*(); - - void replace(T*); - -private: -#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK) && OS(WINDOWS) - friend void ThreadSpecificThreadExit(); -#endif - - // Not implemented. It's technically possible to destroy a thread specific key, but one would need - // to make sure that all values have been destroyed already (usually, that all threads that used it - // have exited). It's unlikely that any user of this call will be in that situation - and having - // a destructor defined can be confusing, given that it has such strong pre-requisites to work correctly. - ~ThreadSpecific(); - - T* get(); - void set(T*); - void static destroy(void* ptr); - -#if USE(PTHREADS) || PLATFORM(QT) || PLATFORM(GTK) || OS(WINDOWS) - struct Data { - WTF_MAKE_NONCOPYABLE(Data); - public: - Data(T* value, ThreadSpecific* owner) : value(value), owner(owner) {} -#if PLATFORM(QT) - ~Data() { owner->destroy(this); } -#endif - - T* value; - ThreadSpecific* owner; -#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK) - 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 m_key; -#elif PLATFORM(GTK) - GStaticPrivate m_key; -#elif OS(WINDOWS) - int m_index; -#endif -#endif -}; - -#if ENABLE(SINGLE_THREADED) -template -inline ThreadSpecific::ThreadSpecific() - : m_value(0) -{ -} - -template -inline T* ThreadSpecific::get() -{ - return m_value; -} - -template -inline void ThreadSpecific::set(T* ptr) -{ - ASSERT(!get()); - m_value = ptr; -} -#else -#if USE(PTHREADS) -template -inline ThreadSpecific::ThreadSpecific() -{ - int error = pthread_key_create(&m_key, destroy); - if (error) - CRASH(); -} - -template -inline T* ThreadSpecific::get() -{ - Data* data = static_cast(pthread_getspecific(m_key)); - return data ? data->value : 0; -} - -template -inline void ThreadSpecific::set(T* ptr) -{ - ASSERT(!get()); - pthread_setspecific(m_key, new Data(ptr, this)); -} - -#elif PLATFORM(QT) - -template -inline ThreadSpecific::ThreadSpecific() -{ -} - -template -inline T* ThreadSpecific::get() -{ - Data* data = static_cast(m_key.localData()); - return data ? data->value : 0; -} - -template -inline void ThreadSpecific::set(T* ptr) -{ - ASSERT(!get()); - Data* data = new Data(ptr, this); - m_key.setLocalData(data); -} - -#elif PLATFORM(GTK) - -template -inline ThreadSpecific::ThreadSpecific() -{ - g_static_private_init(&m_key); -} - -template -inline T* ThreadSpecific::get() -{ - Data* data = static_cast(g_static_private_get(&m_key)); - return data ? data->value : 0; -} - -template -inline void ThreadSpecific::set(T* ptr) -{ - ASSERT(!get()); - Data* data = new Data(ptr, this); - g_static_private_set(&m_key, data, destroy); -} - -#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; - -long& tlsKeyCount(); -DWORD* tlsKeys(); - -template -inline ThreadSpecific::ThreadSpecific() - : m_index(-1) -{ - DWORD tlsKey = TlsAlloc(); - if (tlsKey == TLS_OUT_OF_INDEXES) - CRASH(); - - m_index = InterlockedIncrement(&tlsKeyCount()) - 1; - if (m_index >= kMaxTlsKeySize) - CRASH(); - tlsKeys()[m_index] = tlsKey; -} - -template -inline ThreadSpecific::~ThreadSpecific() -{ - // Does not invoke destructor functions. They will be called from ThreadSpecificThreadExit when the thread is detached. - TlsFree(tlsKeys()[m_index]); -} - -template -inline T* ThreadSpecific::get() -{ - Data* data = static_cast(TlsGetValue(tlsKeys()[m_index])); - return data ? data->value : 0; -} - -template -inline void ThreadSpecific::set(T* ptr) -{ - ASSERT(!get()); - Data* data = new Data(ptr, this); - data->destructor = &ThreadSpecific::destroy; - TlsSetValue(tlsKeys()[m_index], data); -} - -#else -#error ThreadSpecific is not implemented for this platform. -#endif -#endif - -template -inline void ThreadSpecific::destroy(void* ptr) -{ -#if !ENABLE(SINGLE_THREADED) - Data* data = static_cast(ptr); - -#if USE(PTHREADS) - // We want get() to keep working while data destructor works, because it can be called indirectly by the destructor. - // Some pthreads implementations zero out the pointer before calling destroy(), so we temporarily reset it. - pthread_setspecific(data->owner->m_key, ptr); -#elif PLATFORM(GTK) - // See comment as above - g_static_private_set(&data->owner->m_key, data, 0); -#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) - // Do nothing here -#elif PLATFORM(GTK) - g_static_private_set(&data->owner->m_key, 0, 0); -#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 -inline ThreadSpecific::operator T*() -{ - T* ptr = static_cast(get()); - if (!ptr) { - // Set up thread-specific value's memory pointer before invoking constructor, in case any function it calls - // needs to access the value, to avoid recursion. - ptr = static_cast(fastZeroedMalloc(sizeof(T))); - set(ptr); - new (ptr) T; - } - return ptr; -} - -template -inline T* ThreadSpecific::operator->() -{ - return operator T*(); -} - -template -inline T& ThreadSpecific::operator*() -{ - return *operator T*(); -} - -template -inline void ThreadSpecific::replace(T* newPtr) -{ - ASSERT(newPtr); - Data* data = static_cast(pthread_getspecific(m_key)); - ASSERT(data); - data->value->~T(); - fastFree(data->value); - data->value = newPtr; -} - -} - -#endif