⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 threadspecific.h

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 H
字号:
/* * Copyright (C) 2008 Apple Inc. All rights reserved. * Copyright (C) 2009 Jian Li <jianli@chromium.org> * * 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 <wtf/Noncopyable.h>#if USE(PTHREADS)#include <pthread.h>#elif PLATFORM(WIN_OS)#include <windows.h>#endifnamespace WTF {#if !USE(PTHREADS) && PLATFORM(WIN_OS)// ThreadSpecificThreadExit should be called each time when a thread is detached.// This is done automatically for threads created with WTF::createThread.void ThreadSpecificThreadExit();#endiftemplate<typename T> class ThreadSpecific : Noncopyable {public:    ThreadSpecific();    T* operator->();    operator T*();    T& operator*();    ~ThreadSpecific();private:#if !USE(PTHREADS) && PLATFORM(WIN_OS)    friend void ThreadSpecificThreadExit();#endif        T* get();    void set(T*);    void static destroy(void* ptr);#if USE(PTHREADS) || PLATFORM(WIN_OS)    struct Data : Noncopyable {        Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {}        T* value;        ThreadSpecific<T>* owner;#if !USE(PTHREADS)        void (*destructor)(void*);#endif    };#endif#if USE(PTHREADS)    pthread_key_t m_key;#elif PLATFORM(WIN_OS)    int m_index;#endif};#if USE(PTHREADS)template<typename T>inline ThreadSpecific<T>::ThreadSpecific(){    int error = pthread_key_create(&m_key, destroy);    if (error)        CRASH();}template<typename T>inline ThreadSpecific<T>::~ThreadSpecific(){    pthread_key_delete(m_key); // Does not invoke destructor functions.}template<typename T>inline T* ThreadSpecific<T>::get(){    Data* data = static_cast<Data*>(pthread_getspecific(m_key));    return data ? data->value : 0;}template<typename T>inline void ThreadSpecific<T>::set(T* ptr){    ASSERT(!get());    pthread_setspecific(m_key, new Data(ptr, this));}#elif PLATFORM(WIN_OS)// 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];template<typename T>inline ThreadSpecific<T>::ThreadSpecific()    : m_index(-1){    DWORD tls_key = TlsAlloc();    if (tls_key == TLS_OUT_OF_INDEXES)        CRASH();    m_index = InterlockedIncrement(&g_tls_key_count) - 1;    if (m_index >= kMaxTlsKeySize)        CRASH();    g_tls_keys[m_index] = tls_key;}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]);}template<typename T>inline T* ThreadSpecific<T>::get(){    Data* data = static_cast<Data*>(TlsGetValue(g_tls_keys[m_index]));    return data ? data->value : 0;}template<typename T>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);}#else#error ThreadSpecific is not implemented for this platform.#endiftemplate<typename T>inline void ThreadSpecific<T>::destroy(void* ptr){    Data* data = static_cast<Data*>(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);#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);#else#error ThreadSpecific is not implemented for this platform.#endif    delete data;}template<typename T>inline ThreadSpecific<T>::operator T*(){    T* ptr = static_cast<T*>(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<T*>(fastMalloc(sizeof(T)));        set(ptr);        new (ptr) T;    }    return ptr;}template<typename T>inline T* ThreadSpecific<T>::operator->(){    return operator T*();}template<typename T>inline T& ThreadSpecific<T>::operator*(){    return *operator T*();}}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -