Ignore:
Timestamp:
Feb 11, 2009, 11:58:36 PM (16 years ago)
Author:
[email protected]
Message:

2009-02-11 Dmitry Titov <[email protected]>

Reviewed by Alexey Proskuryakov.

https://bugs.webkit.org/show_bug.cgi?id=23705
Fix the UI freeze caused by Worker generating a flood of messages.
Measure time we spend in executing posted work items. If too much time is spent
without returning to the run loop, exit and reschedule.

  • wtf/MainThread.h: Added initializeMainThreadPlatform() to initialize low-level mechanism for posting work items from thread to thread. This removes #ifdefs for WIN and CHROMIUM from platform-independent code.
  • wtf/MainThread.cpp: (WTF::initializeMainThread): (WTF::dispatchFunctionsFromMainThread): Instead of dispatching all work items in the queue, dispatch them one by one and measure elapsed time. After a threshold, reschedule and quit.

(WTF::callOnMainThread):
(WTF::callOnMainThreadAndWait):
Only schedule dispatch if the queue was empty - to avoid many posted messages in the run loop queue.

  • wtf/mac/MainThreadMac.mm: (WTF::scheduleDispatchFunctionsOnMainThread): Use static instance of the mainThreadCaller instead of allocating and releasing it each time. (WTF::initializeMainThreadPlatform):
  • wtf/gtk/MainThreadChromium.cpp: (WTF::initializeMainThreadPlatform):
  • wtf/gtk/MainThreadGtk.cpp: (WTF::initializeMainThreadPlatform):
  • wtf/qt/MainThreadQt.cpp: (WTF::initializeMainThreadPlatform):
  • wtf/win/MainThreadWin.cpp: (WTF::initializeMainThreadPlatform):
  • wtf/wx/MainThreadWx.cpp: (WTF::initializeMainThreadPlatform):
File:
1 edited

Legend:

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

    r40684 r40888  
    3030#include "MainThread.h"
    3131
     32#include "CurrentTime.h"
     33#include "Deque.h"
    3234#include "StdLibExtras.h"
    3335#include "Threading.h"
    34 #include "Vector.h"
    3536
    3637namespace WTF {
     
    4950};
    5051
    51 typedef Vector<FunctionWithContext> FunctionQueue;
     52typedef Deque<FunctionWithContext> FunctionQueue;
    5253
    5354static bool callbacksPaused; // This global variable is only accessed from main thread.
     
    6566}
    6667
    67 #if !PLATFORM(WIN) && !PLATFORM(CHROMIUM)
    6868void initializeMainThread()
    6969{
    7070    mainThreadFunctionQueueMutex();
     71    initializeMainThreadPlatform();
    7172}
    72 #endif
     73
     74// 0.1 sec delays in UI is approximate threshold when they become noticeable. Have a limit that's half of that.
     75static const double maxRunLoopSuspensionTime = 0.05;
    7376
    7477void dispatchFunctionsFromMainThread()
     
    7982        return;
    8083
    81     FunctionQueue queueCopy;
    82     {
    83         MutexLocker locker(mainThreadFunctionQueueMutex());
    84         queueCopy.swap(functionQueue());
    85     }
     84    double startTime = currentTime();
    8685
    87     for (unsigned i = 0; i < queueCopy.size(); ++i) {
    88         FunctionWithContext& invocation = queueCopy[i];
     86    FunctionWithContext invocation;
     87    while (true) {
     88        {
     89            MutexLocker locker(mainThreadFunctionQueueMutex());
     90            if (!functionQueue().size())
     91                break;
     92            invocation = functionQueue().first();
     93            functionQueue().removeFirst();
     94        }
     95
    8996        invocation.function(invocation.context);
    9097        if (invocation.syncFlag)
    9198            invocation.syncFlag->signal();
     99       
     100        // If we are running accumulated functions for too long so UI may become unresponsive, we need to
     101        // yield so the user input can be processed. Otherwise user may not be able to even close the window.
     102        // This code has effect only in case the scheduleDispatchFunctionsOnMainThread() is implemented in a way that
     103        // allows input events to be processed before we are back here.
     104        if (currentTime() - startTime > maxRunLoopSuspensionTime) {
     105            scheduleDispatchFunctionsOnMainThread();
     106            break;
     107        }
    92108    }
    93109}
     
    96112{
    97113    ASSERT(function);
    98 
     114    bool needToSchedule = false;
    99115    {
    100116        MutexLocker locker(mainThreadFunctionQueueMutex());
     117        needToSchedule = functionQueue().size() == 0;
    101118        functionQueue().append(FunctionWithContext(function, context));
    102119    }
    103 
    104     scheduleDispatchFunctionsOnMainThread();
     120    if (needToSchedule)
     121        scheduleDispatchFunctionsOnMainThread();
    105122}
    106123
     
    116133    ThreadCondition syncFlag;
    117134    Mutex conditionMutex;
    118 
     135    bool needToSchedule = false;
    119136    {
    120137        MutexLocker locker(mainThreadFunctionQueueMutex());
     138        needToSchedule = functionQueue().size() == 0;
    121139        functionQueue().append(FunctionWithContext(function, context, &syncFlag));
    122140        conditionMutex.lock();
    123141    }
    124142
    125     scheduleDispatchFunctionsOnMainThread();
     143    if (needToSchedule)
     144        scheduleDispatchFunctionsOnMainThread();
    126145    syncFlag.wait(conditionMutex);
    127146}
Note: See TracChangeset for help on using the changeset viewer.