⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 242694 in webkit


Ignore:
Timestamp:
Mar 10, 2019, 7:36:23 PM (7 years ago)
Author:
Fujii Hironori
Message:

[WTF] Align assumption in RunLoopWin to the other platform's RunLoop
https://bugs.webkit.org/show_bug.cgi?id=181151

Source/WTF:

Reviewed by Don Olmstead.

This patch fixes RunLoop in Windows to align it to the implementations in the other platforms
to use RunLoop more aggressively.

  • wtf/RunLoop.h:

(WTF::RunLoop::Timer::Timer):

  • wtf/win/MainThreadWin.cpp:

(initializeMainThreadPlatform): Call RunLoop::registerRunLoopMessageWindowClass.

  • wtf/win/RunLoopWin.cpp:

(WTF::RunLoop::wndProc):
(WTF::RunLoop::iterate):
(WTF::RunLoop::stop):
PostQuitMessage is only available in the RunLoop's thread. We should post a message and call
it inside this task.

(WTF::RunLoop::registerRunLoopMessageWindowClass):
Changed the return type from bool to void, and added RELEASE_ASSERT to check the return value of RegisterClass.

(WTF::RunLoop::~RunLoop):
When the RunLoop's thread is freed, its associated window is freed. We do not need to do here.

(WTF::RunLoop::TimerBase::timerFired):
(WTF::RunLoop::TimerBase::TimerBase):
(WTF::RunLoop::TimerBase::start):
(WTF::RunLoop::TimerBase::stop):
(WTF::RunLoop::TimerBase::isActive const):
(WTF::RunLoop::TimerBase::secondsUntilFire const):
(WTF::generateTimerID): Deleted.
We can use TimerBase's pointer as ID since it is uintptr_t.

Tools:

Patch by Yusuke Suzuki <Yusuke Suzuki> on 2019-03-10
Reviewed by Don Olmstead.

  • TestWebKitAPI/CMakeLists.txt:
  • TestWebKitAPI/PlatformWin.cmake:

Enable TestWTF RunLoop tests in all platforms.

  • TestWebKitAPI/Tests/WTF/RunLoop.cpp:

(TestWebKitAPI::DerivedOneShotTimer::DerivedOneShotTimer):
(TestWebKitAPI::DerivedOneShotTimer::fired):
(TestWebKitAPI::TEST):
Only a few platforms support nested RunLoop.

(TestWebKitAPI::DerivedRepeatingTimer::DerivedRepeatingTimer):
(TestWebKitAPI::DerivedRepeatingTimer::fired):

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r242624 r242694  
     12019-03-10  Yusuke Suzuki <utatane.tea@gmail.com> and Fujii Hironori  <Hironori.Fujii@sony.com>
     2
     3        [WTF] Align assumption in RunLoopWin to the other platform's RunLoop
     4        https://bugs.webkit.org/show_bug.cgi?id=181151
     5
     6        Reviewed by Don Olmstead.
     7
     8        This patch fixes RunLoop in Windows to align it to the implementations in the other platforms
     9        to use RunLoop more aggressively.
     10
     11        * wtf/RunLoop.h:
     12        (WTF::RunLoop::Timer::Timer):
     13        * wtf/win/MainThreadWin.cpp:
     14        (initializeMainThreadPlatform): Call RunLoop::registerRunLoopMessageWindowClass.
     15        * wtf/win/RunLoopWin.cpp:
     16        (WTF::RunLoop::wndProc):
     17        (WTF::RunLoop::iterate):
     18        (WTF::RunLoop::stop):
     19        PostQuitMessage is only available in the RunLoop's thread. We should post a message and call
     20        it inside this task.
     21
     22        (WTF::RunLoop::registerRunLoopMessageWindowClass):
     23        Changed the return type from bool to void, and added RELEASE_ASSERT to check the return value of RegisterClass.
     24
     25        (WTF::RunLoop::~RunLoop):
     26        When the RunLoop's thread is freed, its associated window is freed. We do not need to do here.
     27
     28        (WTF::RunLoop::TimerBase::timerFired):
     29        (WTF::RunLoop::TimerBase::TimerBase):
     30        (WTF::RunLoop::TimerBase::start):
     31        (WTF::RunLoop::TimerBase::stop):
     32        (WTF::RunLoop::TimerBase::isActive const):
     33        (WTF::RunLoop::TimerBase::secondsUntilFire const):
     34        (WTF::generateTimerID): Deleted.
     35        We can use TimerBase's pointer as ID since it is uintptr_t.
     36
    1372019-03-07  Said Abou-Hallawa  <sabouhallawa@apple.com>
    238
  • trunk/Source/WTF/wtf/RunLoop.h

    r237099 r242694  
    6969#endif
    7070
    71 #if USE(GENERIC_EVENT_LOOP)
     71#if USE(GENERIC_EVENT_LOOP) || USE(WINDOWS_EVENT_LOOP)
    7272    // Run the single iteration of the RunLoop. It consumes the pending tasks and expired timers, but it won't be blocked.
    7373    WTF_EXPORT_PRIVATE static void iterate();
     74#endif
     75
     76#if USE(WINDOWS_EVENT_LOOP)
     77    static void registerRunLoopMessageWindowClass();
    7478#endif
    7579
     
    111115#if USE(WINDOWS_EVENT_LOOP)
    112116        bool isActive(const AbstractLocker&) const;
    113         static void timerFired(RunLoop*, uint64_t ID);
    114         uint64_t m_ID;
     117        void timerFired();
    115118        MonotonicTime m_nextFireDate;
    116119        Seconds m_interval;
    117         bool m_isRepeating;
     120        bool m_isRepeating { false };
     121        bool m_isActive { false };
    118122#elif USE(COCOA_EVENT_LOOP)
    119123        static void timerFired(CFRunLoopTimerRef, void*);
     
    140144        Timer(RunLoop& runLoop, TimerFiredClass* o, TimerFiredFunction f)
    141145            : TimerBase(runLoop)
     146            , m_function(f)
    142147            , m_object(o)
    143             , m_function(f)
    144148        {
    145149        }
     
    148152        void fired() override { (m_object->*m_function)(); }
    149153
     154        // This order should be maintained due to MSVC bug.
     155        // http://computer-programming-forum.com/7-vc.net/6fbc30265f860ad1.htm
     156        TimerFiredFunction m_function;
    150157        TimerFiredClass* m_object;
    151         TimerFiredFunction m_function;
    152158    };
    153159
     
    163169
    164170#if USE(WINDOWS_EVENT_LOOP)
    165     static bool registerRunLoopMessageWindowClass();
    166171    static LRESULT CALLBACK RunLoopWndProc(HWND, UINT, WPARAM, LPARAM);
    167172    LRESULT wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    168173    HWND m_runLoopMessageWindow;
    169174
    170     typedef HashMap<uint64_t, TimerBase*> TimerMap;
    171     Lock m_activeTimersLock;
    172     TimerMap m_activeTimers;
     175    Lock m_loopLock;
    173176#elif USE(COCOA_EVENT_LOOP)
    174177    static void performWork(void*);
  • trunk/Source/WTF/wtf/win/MainThreadWin.cpp

    r237099 r242694  
    3232
    3333#include <wtf/Assertions.h>
     34#include <wtf/RunLoop.h>
    3435#include <wtf/Threading.h>
    3536#include <wtf/WindowsExtras.h>
     
    6970
    7071    Thread::initializeCurrentThreadInternal("Main Thread");
     72    RunLoop::registerRunLoopMessageWindowClass();
    7173}
    7274
  • trunk/Source/WTF/wtf/win/RunLoopWin.cpp

    r239093 r242694  
    5757        return 0;
    5858    case WM_TIMER:
    59         RunLoop::TimerBase::timerFired(this, wParam);
     59        bitwise_cast<RunLoop::TimerBase*>(wParam)->timerFired();
    6060        return 0;
    6161    }
     
    7575}
    7676
     77void RunLoop::iterate()
     78{
     79    MSG message;
     80    while (::PeekMessage(&message, 0, 0, 0, PM_REMOVE)) {
     81        ::TranslateMessage(&message);
     82        ::DispatchMessage(&message);
     83    }
     84}
     85
    7786void RunLoop::stop()
    7887{
    79     ::PostQuitMessage(0);
     88    // RunLoop::stop() can be called from threads unrelated to this RunLoop.
     89    // We should post a message that call PostQuitMessage in RunLoop's thread.
     90    dispatch([] {
     91        ::PostQuitMessage(0);
     92    });
    8093}
    8194
    82 bool RunLoop::registerRunLoopMessageWindowClass()
     95void RunLoop::registerRunLoopMessageWindowClass()
    8396{
    84     // FIXME: This really only needs to be called once.
    85 
    86     WNDCLASS windowClass { };
     97    WNDCLASS windowClass = { };
    8798    windowClass.lpfnWndProc     = RunLoop::RunLoopWndProc;
    8899    windowClass.cbWndExtra      = sizeof(RunLoop*);
    89100    windowClass.lpszClassName   = kRunLoopMessageWindowClassName;
    90 
    91     return !!::RegisterClass(&windowClass);
     101    bool result = ::RegisterClass(&windowClass);
     102    RELEASE_ASSERT(result);
    92103}
    93104
    94105RunLoop::RunLoop()
    95106{
    96     registerRunLoopMessageWindowClass();
    97 
    98107    m_runLoopMessageWindow = ::CreateWindow(kRunLoopMessageWindowClassName, 0, 0,
    99108        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, 0, 0, this);
     
    103112RunLoop::~RunLoop()
    104113{
    105     // FIXME: Tear down the work item queue here.
    106114}
    107115
     
    115123// RunLoop::Timer
    116124
    117 void RunLoop::TimerBase::timerFired(RunLoop* runLoop, uint64_t ID)
     125void RunLoop::TimerBase::timerFired()
    118126{
    119     TimerBase* timer = nullptr;
    120127    {
    121         LockHolder locker(runLoop->m_activeTimersLock);
    122         TimerMap::iterator it = runLoop->m_activeTimers.find(ID);
    123         if (it == runLoop->m_activeTimers.end()) {
    124             // The timer must have been stopped after the WM_TIMER message was posted to the message queue.
     128        LockHolder locker(m_runLoop->m_loopLock);
     129
     130        if (!m_isActive)
    125131            return;
    126         }
    127132
    128         timer = it->value;
    129 
    130         if (!timer->m_isRepeating) {
    131             runLoop->m_activeTimers.remove(it);
    132             ::KillTimer(runLoop->m_runLoopMessageWindow, ID);
     133        if (!m_isRepeating) {
     134            m_isActive = false;
     135            ::KillTimer(m_runLoop->m_runLoopMessageWindow, bitwise_cast<uintptr_t>(this));
    133136        } else
    134             timer->m_nextFireDate = MonotonicTime::now() + timer->m_interval;
     137            m_nextFireDate = MonotonicTime::now() + m_interval;
    135138    }
    136139
    137     timer->fired();
    138 }
    139 
    140 static uint64_t generateTimerID()
    141 {
    142     static uint64_t uniqueTimerID = 1;
    143     return uniqueTimerID++;
     140    fired();
    144141}
    145142
    146143RunLoop::TimerBase::TimerBase(RunLoop& runLoop)
    147144    : m_runLoop(runLoop)
    148     , m_ID(generateTimerID())
    149     , m_isRepeating(false)
    150145{
    151146}
     
    158153void RunLoop::TimerBase::start(Seconds nextFireInterval, bool repeat)
    159154{
    160     LockHolder locker(m_runLoop->m_activeTimersLock);
     155    LockHolder locker(m_runLoop->m_loopLock);
    161156    m_isRepeating = repeat;
    162     m_runLoop->m_activeTimers.set(m_ID, this);
     157    m_isActive = true;
    163158    m_interval = nextFireInterval;
    164159    m_nextFireDate = MonotonicTime::now() + m_interval;
    165     ::SetTimer(m_runLoop->m_runLoopMessageWindow, m_ID, nextFireInterval.millisecondsAs<unsigned>(), 0);
     160    ::SetTimer(m_runLoop->m_runLoopMessageWindow, bitwise_cast<uintptr_t>(this), nextFireInterval.millisecondsAs<UINT>(), 0);
    166161}
    167162
    168163void RunLoop::TimerBase::stop()
    169164{
    170     LockHolder locker(m_runLoop->m_activeTimersLock);
    171     TimerMap::iterator it = m_runLoop->m_activeTimers.find(m_ID);
    172     if (it == m_runLoop->m_activeTimers.end())
     165    LockHolder locker(m_runLoop->m_loopLock);
     166    if (!isActive(locker))
    173167        return;
    174168
    175     m_runLoop->m_activeTimers.remove(it);
    176     ::KillTimer(m_runLoop->m_runLoopMessageWindow, m_ID);
     169    m_isActive = false;
     170    ::KillTimer(m_runLoop->m_runLoopMessageWindow, bitwise_cast<uintptr_t>(this));
    177171}
    178172
    179173bool RunLoop::TimerBase::isActive(const AbstractLocker&) const
    180174{
    181     return m_runLoop->m_activeTimers.contains(m_ID);
     175    return m_isActive;
    182176}
    183177
    184178bool RunLoop::TimerBase::isActive() const
    185179{
    186     LockHolder locker(m_runLoop->m_activeTimersLock);
     180    LockHolder locker(m_runLoop->m_loopLock);
    187181    return isActive(locker);
    188182}
     
    190184Seconds RunLoop::TimerBase::secondsUntilFire() const
    191185{
    192     LockHolder locker(m_runLoop->m_activeTimersLock);
     186    LockHolder locker(m_runLoop->m_loopLock);
    193187    if (isActive(locker))
    194188        return std::max<Seconds>(m_nextFireDate - MonotonicTime::now(), 0_s);
     
    196190}
    197191
    198 
    199192} // namespace WTF
  • trunk/Tools/ChangeLog

    r242693 r242694  
     12019-03-10  Yusuke Suzuki <utatane.tea@gmail.com>
     2
     3        [WTF] Align assumption in RunLoopWin to the other platform's RunLoop
     4        https://bugs.webkit.org/show_bug.cgi?id=181151
     5
     6        Reviewed by Don Olmstead.
     7
     8        * TestWebKitAPI/CMakeLists.txt:
     9        * TestWebKitAPI/PlatformWin.cmake:
     10        Enable TestWTF RunLoop tests in all platforms.
     11
     12        * TestWebKitAPI/Tests/WTF/RunLoop.cpp:
     13        (TestWebKitAPI::DerivedOneShotTimer::DerivedOneShotTimer):
     14        (TestWebKitAPI::DerivedOneShotTimer::fired):
     15        (TestWebKitAPI::TEST):
     16        Only a few platforms support nested RunLoop.
     17
     18        (TestWebKitAPI::DerivedRepeatingTimer::DerivedRepeatingTimer):
     19        (TestWebKitAPI::DerivedRepeatingTimer::fired):
     20
    1212019-03-10  David Quesada  <david_quesada@apple.com>
    222
  • trunk/Tools/TestWebKitAPI/CMakeLists.txt

    r242127 r242694  
    154154    ${TESTWEBKITAPI_DIR}/Tests/WTF/RefLogger.cpp
    155155    ${TESTWEBKITAPI_DIR}/Tests/WTF/RefPtr.cpp
     156    ${TESTWEBKITAPI_DIR}/Tests/WTF/RunLoop.cpp
    156157    ${TESTWEBKITAPI_DIR}/Tests/WTF/SHA1.cpp
    157158    ${TESTWEBKITAPI_DIR}/Tests/WTF/SaturatedArithmeticOperations.cpp
     
    187188    list(APPEND TestWTF_SOURCES
    188189        ${TESTWEBKITAPI_DIR}/Tests/WTF/FileSystem.cpp
    189         ${TESTWEBKITAPI_DIR}/Tests/WTF/RunLoop.cpp
    190190    )
    191191endif ()
  • trunk/Tools/TestWebKitAPI/PlatformWin.cmake

    r242279 r242694  
    108108    ${test_main_SOURCES}
    109109    ${TestWTF_SOURCES}
     110    ${TESTWEBKITAPI_DIR}/win/UtilitiesWin.cpp
    110111)
    111112set_target_properties(TestWTFLib PROPERTIES OUTPUT_NAME "TestWTFLib")
  • trunk/Tools/TestWebKitAPI/Tests/WTF/RunLoop.cpp

    r235788 r242694  
    2828#include "Utilities.h"
    2929#include <wtf/RunLoop.h>
     30#include <wtf/Threading.h>
    3031
    3132namespace TestWebKitAPI {
     
    5556}
    5657
    57 TEST(WTF_RunLoop, NestedRunLoop)
    58 {
    59     RunLoop::initializeMainRunLoop();
     58class DerivedOneShotTimer : public RunLoop::Timer<DerivedOneShotTimer> {
     59public:
     60    DerivedOneShotTimer(bool& testFinished)
     61        : RunLoop::Timer<DerivedOneShotTimer>(RunLoop::current(), this, &DerivedOneShotTimer::fired)
     62        , m_testFinished(testFinished)
     63    {
     64    }
    6065
    61     bool testFinished = false;
    62     RunLoop::current().dispatch([&] {
    63         RunLoop::current().dispatch([&] {
    64             testFinished = true;
    65         });
    66         Util::run(&testFinished);
    67     });
     66    void fired()
     67    {
     68        m_testFinished = true;
     69        stop();
     70    }
    6871
    69     Util::run(&testFinished);
    70 }
     72private:
     73    bool& m_testFinished;
     74};
     75
    7176
    7277TEST(WTF_RunLoop, OneShotTimer)
     
    7580
    7681    bool testFinished = false;
     82    DerivedOneShotTimer timer(testFinished);
     83    timer.startOneShot(100_ms);
     84    Util::run(&testFinished);
     85}
    7786
    78     class DerivedTimer : public RunLoop::Timer<DerivedTimer> {
    79     public:
    80         DerivedTimer(bool& testFinished)
    81             : RunLoop::Timer<DerivedTimer>(RunLoop::current(), this, &DerivedTimer::fired)
    82             , m_testFinished(testFinished)
    83         {
    84         }
     87class DerivedRepeatingTimer : public RunLoop::Timer<DerivedRepeatingTimer> {
     88public:
     89    DerivedRepeatingTimer(bool& testFinished)
     90        : RunLoop::Timer<DerivedRepeatingTimer>(RunLoop::current(), this, &DerivedRepeatingTimer::fired)
     91        , m_testFinished(testFinished)
     92    {
     93    }
    8594
    86         void fired()
    87         {
     95    void fired()
     96    {
     97        if (++m_count == 10) {
    8898            m_testFinished = true;
    8999            stop();
    90100        }
     101    }
    91102
    92     private:
    93         bool& m_testFinished;
    94     };
     103private:
     104    unsigned m_count { 0 };
     105    bool& m_testFinished;
     106};
    95107
    96     {
    97         DerivedTimer timer(testFinished);
    98         timer.startOneShot(100_ms);
    99         Util::run(&testFinished);
    100     }
    101 }
    102108
    103109TEST(WTF_RunLoop, RepeatingTimer)
     
    106112
    107113    bool testFinished = false;
    108 
    109     class DerivedTimer : public RunLoop::Timer<DerivedTimer> {
    110     public:
    111         DerivedTimer(bool& testFinished)
    112             : RunLoop::Timer<DerivedTimer>(RunLoop::current(), this, &DerivedTimer::fired)
    113             , m_testFinished(testFinished)
    114         {
    115         }
    116 
    117         void fired()
    118         {
    119             if (++m_count == 10) {
    120                 m_testFinished = true;
    121                 stop();
    122             }
    123         }
    124 
    125     private:
    126         unsigned m_count { 0 };
    127         bool& m_testFinished;
    128     };
    129 
    130     {
    131         DerivedTimer timer(testFinished);
    132         timer.startRepeating(10_ms);
    133         Util::run(&testFinished);
    134     }
     114    DerivedRepeatingTimer timer(testFinished);
     115    timer.startRepeating(10_ms);
     116    Util::run(&testFinished);
    135117}
    136118
    137119TEST(WTF_RunLoop, ManyTimes)
    138120{
    139     RunLoop::initializeMainRunLoop();
    140 
    141121    class Counter {
    142122    public:
     
    156136    };
    157137
    158     Counter counter;
    159 
    160     RunLoop::current().dispatch([&counter] {
    161         counter.run();
    162     });
    163     RunLoop::run();
     138    Thread::create("RunLoopManyTimes", [] {
     139        Counter counter;
     140        RunLoop::current().dispatch([&counter] {
     141            counter.run();
     142        });
     143        RunLoop::run();
     144    })->waitForCompletion();
    164145}
    165146
Note: See TracChangeset for help on using the changeset viewer.