Ignore:
Timestamp:
Feb 23, 2008, 11:50:04 AM (17 years ago)
Author:
[email protected]
Message:

2008-02-23 Alexey Proskuryakov <[email protected]>

Reviewed by Darin.

Move basic threading support from WebCore to WTF.

File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/wtf/ThreadingWin.cpp

    r30421 r30522  
    2828
    2929#include "config.h"
    30 #include "Logging.h"
    31 #include "Page.h"
    3230#include "Threading.h"
    33 #include <errno.h>
     31
    3432#include <windows.h>
    3533#include <wtf/HashMap.h>
    3634
    37 namespace WebCore {
    38 
    39 struct FunctionWithContext {
    40     MainThreadFunction* function;
    41     void* context;
    42     FunctionWithContext(MainThreadFunction* f = 0, void* c = 0) : function(f), context(c) { }
    43 };
    44 
    45 typedef Vector<FunctionWithContext> FunctionQueue;
    46 
    47 static HWND threadingWindowHandle = 0;
    48 static UINT threadingFiredMessage = 0;
    49 const LPCWSTR kThreadingWindowClassName = L"ThreadingWindowClass";
    50 static bool processingCustomThreadingMessage = false;
     35namespace WTF {
    5136
    5237static Mutex& threadMapMutex()
     
    9580    storeThreadHandleByIdentifier(threadIdentifier, threadHandle);
    9681
    97     LOG(Threading, "Created thread with thread id %u", threadID);
    9882    return threadID;
    9983}
     
    132116}
    133117
    134 static Mutex& functionQueueMutex()
     118Mutex::Mutex()
    135119{
    136     static Mutex staticFunctionQueueMutex;
    137     return staticFunctionQueueMutex;
     120    m_mutex.m_recursionCount = 0;
     121    ::InitializeCriticalSection(&m_mutex.m_internalMutex);
    138122}
    139123
    140 static FunctionQueue& functionQueue()
     124Mutex::~Mutex()
    141125{
    142     static FunctionQueue staticFunctionQueue;
    143     return staticFunctionQueue;
     126    ::DeleteCriticalSection(&m_mutex.m_internalMutex);
    144127}
    145128
    146 static void callFunctionsOnMainThread()
     129void Mutex::lock()
    147130{
    148     FunctionQueue queueCopy;
    149     {
    150         MutexLocker locker(functionQueueMutex());
    151         queueCopy.swap(functionQueue());
     131    ::EnterCriticalSection(&m_mutex.m_internalMutex);
     132    ++m_mutex.m_recursionCount;
     133}
     134   
     135bool Mutex::tryLock()
     136{
     137    // This method is modeled after the behavior of pthread_mutex_trylock,
     138    // which will return an error if the lock is already owned by the
     139    // current thread.  Since the primitive Win32 'TryEnterCriticalSection'
     140    // treats this as a successful case, it changes the behavior of several
     141    // tests in WebKit that check to see if the current thread already
     142    // owned this mutex (see e.g., IconDatabase::getOrCreateIconRecord)
     143    DWORD result = ::TryEnterCriticalSection(&m_mutex.m_internalMutex);
     144   
     145    if (result != 0) {       // We got the lock
     146        // If this thread already had the lock, we must unlock and
     147        // return false so that we mimic the behavior of POSIX's
     148        // pthread_mutex_trylock:
     149        if (m_mutex.m_recursionCount > 0) {
     150            ::LeaveCriticalSection(&m_mutex.m_internalMutex);
     151            return false;
     152        }
     153
     154        ++m_mutex.m_recursionCount;
     155        return true;
    152156    }
    153157
    154     LOG(Threading, "Calling %u functions on the main thread", queueCopy.size());
    155     for (unsigned i = 0; i < queueCopy.size(); ++i)
    156         queueCopy[i].function(queueCopy[i].context);
     158    return false;
    157159}
    158160
    159 LRESULT CALLBACK ThreadingWindowWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
     161void Mutex::unlock()
    160162{
    161     if (message == threadingFiredMessage) {
    162         processingCustomThreadingMessage = true;
    163         callFunctionsOnMainThread();
    164         processingCustomThreadingMessage = false;
    165     } else
    166         return DefWindowProc(hWnd, message, wParam, lParam);
    167     return 0;
     163    --m_mutex.m_recursionCount;
     164    ::LeaveCriticalSection(&m_mutex.m_internalMutex);
    168165}
    169166
    170 void initializeThreading()
    171 {
    172     if (threadingWindowHandle)
    173         return;
    174    
    175     WNDCLASSEX wcex;
    176     memset(&wcex, 0, sizeof(WNDCLASSEX));
    177     wcex.cbSize = sizeof(WNDCLASSEX);
    178     wcex.lpfnWndProc    = ThreadingWindowWndProc;
    179     wcex.hInstance      = Page::instanceHandle();
    180     wcex.lpszClassName  = kThreadingWindowClassName;
    181     RegisterClassEx(&wcex);
    182 
    183     threadingWindowHandle = CreateWindow(kThreadingWindowClassName, 0, 0,
    184        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, 0, Page::instanceHandle(), 0);
    185     threadingFiredMessage = RegisterWindowMessage(L"com.apple.WebKit.MainThreadFired");
    186 }
    187    
    188 void callOnMainThread(MainThreadFunction* function, void* context)
    189 {
    190     ASSERT(function);
    191     ASSERT(threadingWindowHandle);
    192 
    193     if (processingCustomThreadingMessage)
    194         LOG(Threading, "callOnMainThread() called recursively.  Beware of nested PostMessage()s");
    195 
    196     {
    197         MutexLocker locker(functionQueueMutex());
    198         functionQueue().append(FunctionWithContext(function, context));
    199     }
    200 
    201     PostMessage(threadingWindowHandle, threadingFiredMessage, 0, 0);
    202 }
    203 
    204 } // namespace WebCore
     167} // namespace WTF
Note: See TracChangeset for help on using the changeset viewer.