Ignore:
Timestamp:
Jan 8, 2009, 8:47:14 AM (16 years ago)
Author:
[email protected]
Message:

2009-01-08 Jian Li <[email protected]>

Reviewed by Alexey Proskuryakov.

Add Win32 implementation of ThreadSpecific.
https://bugs.webkit.org/show_bug.cgi?id=22614

  • JavaScriptCore.vcproj/WTF/WTF.vcproj:
  • wtf/ThreadSpecific.h: (WTF::ThreadSpecific::ThreadSpecific): (WTF::ThreadSpecific::~ThreadSpecific): (WTF::ThreadSpecific::get): (WTF::ThreadSpecific::set): (WTF::ThreadSpecific::destroy):
  • wtf/ThreadSpecificWin.cpp: Added. (WTF::ThreadSpecificThreadExit):
  • wtf/ThreadingWin.cpp: (WTF::wtfThreadEntryPoint):
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/wtf/ThreadSpecific.h

    r39672 r39708  
    11/*
    22 * Copyright (C) 2008 Apple Inc. All rights reserved.
     3 * Copyright (C) 2009 Jian Li <[email protected]>
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    2728 */
    2829
     30/* Thread local storage is implemented by using either pthread API or Windows
     31 * native API. There is subtle semantic discrepancy for the cleanup function
     32 * implementation as noted below:
     33 *   @ In pthread implementation, the destructor function will be called
     34 *     repeatedly if there is still non-NULL value associated with the function.
     35 *   @ In Windows native implementation, the destructor function will be called
     36 *     only once.
     37 * This semantic discrepancy does not impose any problem because nowhere in
     38 * WebKit the repeated call bahavior is utilized.
     39 */
     40
    2941#ifndef WTF_ThreadSpecific_h
    3042#define WTF_ThreadSpecific_h
     
    3244#include <wtf/Noncopyable.h>
    3345
    34 #if USE(PTHREADS) || PLATFORM(WIN)
    35 // Windows currently doesn't use pthreads for basic threading, but implementing destructor functions is easier
    36 // with pthreads, so we use it here.
     46#if USE(PTHREADS)
    3747#include <pthread.h>
     48#elif PLATFORM(WIN_OS)
     49#include <windows.h>
    3850#endif
    3951
    4052namespace WTF {
     53
     54#if !USE(PTHREADS) && PLATFORM(WIN_OS)
     55// ThreadSpecificThreadExit should be called each time when a thread is detached.
     56// This is done automatically for threads created with WTF::createThread.
     57void ThreadSpecificThreadExit();
     58#endif
    4159
    4260template<typename T> class ThreadSpecific : Noncopyable {
     
    4967
    5068private:
     69#if !USE(PTHREADS) && PLATFORM(WIN_OS)
     70    friend void ThreadSpecificThreadExit();
     71#endif
     72   
    5173    T* get();
    5274    void set(T*);
    5375    void static destroy(void* ptr);
    5476
    55 #if USE(PTHREADS) || PLATFORM(WIN)
     77#if USE(PTHREADS) || PLATFORM(WIN_OS)
    5678    struct Data : Noncopyable {
    5779        Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {}
     
    5981        T* value;
    6082        ThreadSpecific<T>* owner;
     83#if !USE(PTHREADS)
     84        void (*destructor)(void*);
     85#endif
    6186    };
    62 
     87#endif
     88
     89#if USE(PTHREADS)
    6390    pthread_key_t m_key;
     91#elif PLATFORM(WIN_OS)
     92    int m_index;
    6493#endif
    6594};
    6695
    67 #if USE(PTHREADS) || PLATFORM(WIN)
     96#if USE(PTHREADS)
    6897template<typename T>
    6998inline ThreadSpecific<T>::ThreadSpecific()
     
    94123}
    95124
     125#elif PLATFORM(WIN_OS)
     126
     127// The maximum number of TLS keys that can be created. For simplification, we assume that:
     128// 1) Once the instance of ThreadSpecific<> is created, it will not be destructed until the program dies.
     129// 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed number should be far enough.
     130const int kMaxTlsKeySize = 256;
     131
     132extern long g_tls_key_count;
     133extern DWORD g_tls_keys[kMaxTlsKeySize];
     134
     135template<typename T>
     136inline ThreadSpecific<T>::ThreadSpecific()
     137    : m_index(-1)
     138{
     139    DWORD tls_key = TlsAlloc();
     140    if (tls_key == TLS_OUT_OF_INDEXES)
     141        CRASH();
     142
     143    m_index = InterlockedIncrement(&g_tls_key_count) - 1;
     144    if (m_index >= kMaxTlsKeySize)
     145        CRASH();
     146    g_tls_keys[m_index] = tls_key;
     147}
     148
     149template<typename T>
     150inline ThreadSpecific<T>::~ThreadSpecific()
     151{
     152    // Does not invoke destructor functions. They will be called from ThreadSpecificThreadExit when the thread is detached.
     153    TlsFree(g_tls_keys[m_index]);
     154}
     155
     156template<typename T>
     157inline T* ThreadSpecific<T>::get()
     158{
     159    Data* data = static_cast<Data*>(TlsGetValue(g_tls_keys[m_index]));
     160    return data ? data->value : 0;
     161}
     162
     163template<typename T>
     164inline void ThreadSpecific<T>::set(T* ptr)
     165{
     166    ASSERT(!get());
     167    Data* data = new Data(ptr, this);
     168    data->destructor = &ThreadSpecific<T>::destroy;
     169    TlsSetValue(g_tls_keys[m_index], data);
     170}
     171
     172#else
     173#error ThreadSpecific is not implemented for this platform.
     174#endif
     175
    96176template<typename T>
    97177inline void ThreadSpecific<T>::destroy(void* ptr)
     
    99179    Data* data = static_cast<Data*>(ptr);
    100180
     181#if USE(PTHREADS)
    101182    // We want get() to keep working while data destructor works, because it can be called indirectly by the destructor.
    102183    // Some pthreads implementations zero out the pointer before calling destroy(), so we temporarily reset it.
    103184    pthread_setspecific(data->owner->m_key, ptr);
     185#endif
     186   
    104187    data->value->~T();
    105188    fastFree(data->value);
     189
     190#if USE(PTHREADS)
    106191    pthread_setspecific(data->owner->m_key, 0);
    107     delete data;
    108 }
    109 
     192#elif PLATFORM(WIN_OS)
     193    TlsSetValue(g_tls_keys[data->owner->m_index], 0);
    110194#else
    111195#error ThreadSpecific is not implemented for this platform.
    112196#endif
     197
     198    delete data;
     199}
    113200
    114201template<typename T>
Note: See TracChangeset for help on using the changeset viewer.