165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch/*
265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * Copyright (C) 2010 Apple Inc. All rights reserved.
365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch *
465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * Redistribution and use in source and binary forms, with or without
565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * modification, are permitted provided that the following conditions
665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * are met:
765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * 1. Redistributions of source code must retain the above copyright
865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch *    notice, this list of conditions and the following disclaimer.
965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * 2. Redistributions in binary form must reproduce the above copyright
1065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch *    notice, this list of conditions and the following disclaimer in the
1165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch *    documentation and/or other materials provided with the distribution.
1265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch *
1365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
1465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
1565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
1765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
2365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * THE POSSIBILITY OF SUCH DAMAGE.
2465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch */
2565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "config.h"
2765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "RunLoop.h"
2865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "BinarySemaphore.h"
3065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "WorkItem.h"
312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include <wtf/CurrentTime.h>
322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochusing namespace CoreIPC;
342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochusing namespace std;
3565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
3665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic const UINT PerformWorkMessage = WM_USER + 1;
3765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic const LPWSTR kRunLoopMessageWindowClassName = L"RunLoopMessageWindow";
3865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
3965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochLRESULT CALLBACK RunLoop::RunLoopWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
4065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
4165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    LONG_PTR longPtr = ::GetWindowLongPtr(hWnd, 0);
4265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
4365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (RunLoop* runLoop = reinterpret_cast<RunLoop*>(longPtr))
4465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return runLoop->wndProc(hWnd, message, wParam, lParam);
4565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
4665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (message == WM_CREATE) {
4765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
4865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
4965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // Associate the RunLoop with the window.
5065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        ::SetWindowLongPtr(hWnd, 0, (LONG_PTR)createStruct->lpCreateParams);
5165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return 0;
5265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
5365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
5465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return ::DefWindowProc(hWnd, message, wParam, lParam);
5565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
5665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
5765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochLRESULT RunLoop::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
5865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
5965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    switch (message) {
6065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    case PerformWorkMessage:
6165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        performWork();
6265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return 0;
6365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    case WM_TIMER:
6465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        RunLoop::TimerBase::timerFired(this, wParam);
6565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return 0;
6665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
6765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
6865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return ::DefWindowProc(hWnd, message, wParam, lParam);
6965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
7065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
7165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid RunLoop::run()
7265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
7365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    MSG message;
7465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    while (BOOL result = ::GetMessage(&message, 0, 0, 0)) {
7565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (result == -1)
7665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            break;
7765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        ::TranslateMessage(&message);
7865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        ::DispatchMessage(&message);
7965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
8065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
8165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool RunLoop::dispatchSentMessagesUntil(const Vector<HWND>& windows, CoreIPC::BinarySemaphore& semaphore, double absoluteTime)
832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (windows.isEmpty())
852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return semaphore.wait(absoluteTime);
862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    HANDLE handle = semaphore.event();
882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    DWORD handleCount = 1;
892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    while (true) {
912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        DWORD interval = absoluteTimeToWaitTimeoutInterval(absoluteTime);
922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!interval) {
932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // Consider the wait to have timed out, even if the semaphore is currently signaled.
942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // This matches the WTF::ThreadCondition implementation of BinarySemaphore::wait.
952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        DWORD result = ::MsgWaitForMultipleObjectsEx(handleCount, &handle, interval, QS_SENDMESSAGE, 0);
992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (result == WAIT_OBJECT_0) {
1002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // The semaphore was signaled.
1012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return true;
1022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
1032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (result == WAIT_TIMEOUT) {
1042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // absoluteTime was reached.
1052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
1062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
1072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (result == WAIT_OBJECT_0 + handleCount) {
1082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // One or more sent messages are available. Process sent messages for all the windows
1092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // we were given, since we don't have a way of knowing which window has available sent
1102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // messages.
1112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            for (size_t i = 0; i < windows.size(); ++i) {
1122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                MSG message;
1132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                ::PeekMessageW(&message, windows[i], 0, 0, PM_NOREMOVE | PM_QS_SENDMESSAGE);
1142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            }
1152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            continue;
1162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
1172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_WITH_MESSAGE(result != WAIT_FAILED, "::MsgWaitForMultipleObjectsEx failed with error %lu", ::GetLastError());
1182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_WITH_MESSAGE(false, "::MsgWaitForMultipleObjectsEx returned unexpected result %lu", result);
1192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
1202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
1212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
1222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid RunLoop::stop()
12465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
12565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ::PostQuitMessage(0);
12665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
12765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
12865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochbool RunLoop::registerRunLoopMessageWindowClass()
12965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
13065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // FIXME: This really only needs to be called once.
13165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
13265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    WNDCLASSEX windowClass = { 0 };
13365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    windowClass.cbSize          = sizeof(windowClass);
13465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    windowClass.lpfnWndProc     = RunLoop::RunLoopWndProc;
13565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    windowClass.cbWndExtra      = sizeof(RunLoop*);
13665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    windowClass.lpszClassName   = kRunLoopMessageWindowClassName;
13765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
13865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return !!::RegisterClassEx(&windowClass);
13965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
14065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
14165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochRunLoop::RunLoop()
14265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
14365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    registerRunLoopMessageWindowClass();
14465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
14565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_runLoopMessageWindow = ::CreateWindow(kRunLoopMessageWindowClassName, 0, 0,
14665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                                            CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
14765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                                            HWND_MESSAGE, 0, 0, this);
14865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(::IsWindow(m_runLoopMessageWindow));
14965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
15065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
15165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochRunLoop::~RunLoop()
15265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
15365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // FIXME: Tear down the work item queue here.
15465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
15565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
15665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid RunLoop::wakeUp()
15765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
15865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // FIXME: No need to wake up the run loop if we've already called scheduleWork
15965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // before the run loop has had the time to respond.
16065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ::PostMessage(m_runLoopMessageWindow, PerformWorkMessage, reinterpret_cast<WPARAM>(this), 0);
16165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
16265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
16365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch// RunLoop::Timer
16465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
16565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid RunLoop::TimerBase::timerFired(RunLoop* runLoop, uint64_t ID)
16665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
16765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    TimerMap::iterator it = runLoop->m_activeTimers.find(ID);
1682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (it == runLoop->m_activeTimers.end()) {
1692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // The timer must have been stopped after the WM_TIMER message was posted to the message queue.
1702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return;
1712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
1722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
17365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    TimerBase* timer = it->second;
17465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
17565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!timer->m_isRepeating) {
17665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        runLoop->m_activeTimers.remove(it);
17765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        ::KillTimer(runLoop->m_runLoopMessageWindow, ID);
17865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
17965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
18065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    timer->fired();
18165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
18265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
18365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic uint64_t generateTimerID()
18465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
18565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    static uint64_t uniqueTimerID = 1;
18665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return uniqueTimerID++;
18765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
18865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
18965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochRunLoop::TimerBase::TimerBase(RunLoop* runLoop)
19065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    : m_runLoop(runLoop)
19165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    , m_ID(generateTimerID())
19265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    , m_isRepeating(false)
19365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
19465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
19565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
19665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochRunLoop::TimerBase::~TimerBase()
19765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
19865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    stop();
19965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
20065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
20165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid RunLoop::TimerBase::start(double nextFireInterval, bool repeat)
20265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
20365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_isRepeating = repeat;
20465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_runLoop->m_activeTimers.set(m_ID, this);
20581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ::SetTimer(m_runLoop->m_runLoopMessageWindow, m_ID, nextFireInterval * 1000, 0);
20665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
20765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
20865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid RunLoop::TimerBase::stop()
20965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
21065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    TimerMap::iterator it = m_runLoop->m_activeTimers.find(m_ID);
21165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (it == m_runLoop->m_activeTimers.end())
21265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return;
21365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
21465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_runLoop->m_activeTimers.remove(it);
21565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ::KillTimer(m_runLoop->m_runLoopMessageWindow, m_ID);
21665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
21765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
21865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochbool RunLoop::TimerBase::isActive() const
21965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
22065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return m_runLoop->m_activeTimers.contains(m_ID);
22165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
222