void dispatchFunctionsFromMainThread() { ASSERT(isMainThread()); if (callbacksPaused) return; double startTime = currentTime(); FunctionWithContext invocation; while (true) { { MutexLocker locker(mainThreadFunctionQueueMutex()); if (!functionQueue().size()) break; invocation = functionQueue().first(); functionQueue().removeFirst(); } invocation.function(invocation.context); if (invocation.syncFlag) invocation.syncFlag->signal(); // If we are running accumulated functions for too long so UI may become unresponsive, we need to // yield so the user input can be processed. Otherwise user may not be able to even close the window. // This code has effect only in case the scheduleDispatchFunctionsOnMainThread() is implemented in a way that // allows input events to be processed before we are back here. if (currentTime() - startTime > maxRunLoopSuspensionTime) { scheduleDispatchFunctionsOnMainThread(); break; } } }
void dispatchFunctionsFromMainThread() { ASSERT(isMainThread()); if (callbacksPaused) return; auto startTime = std::chrono::steady_clock::now(); std::function<void ()> function; while (true) { { std::lock_guard<StaticLock> lock(mainThreadFunctionQueueMutex); if (!functionQueue().size()) break; function = functionQueue().takeFirst(); } function(); // If we are running accumulated functions for too long so UI may become unresponsive, we need to // yield so the user input can be processed. Otherwise user may not be able to even close the window. // This code has effect only in case the scheduleDispatchFunctionsOnMainThread() is implemented in a way that // allows input events to be processed before we are back here. if (std::chrono::steady_clock::now() - startTime > maxRunLoopSuspensionTime) { scheduleDispatchFunctionsOnMainThread(); break; } } }
void callOnMainThread(MainThreadFunction* function, void* context) { ASSERT(function); bool needToSchedule = false; { MutexLocker locker(mainThreadFunctionQueueMutex()); needToSchedule = functionQueue().size() == 0; functionQueue().append(FunctionWithContext(function, context)); } if (needToSchedule) scheduleDispatchFunctionsOnMainThread(); }
void callOnMainThread(std::function<void ()> function) { ASSERT(function); bool needToSchedule = false; { std::lock_guard<StaticLock> lock(mainThreadFunctionQueueMutex); needToSchedule = functionQueue().size() == 0; functionQueue().append(WTFMove(function)); } if (needToSchedule) scheduleDispatchFunctionsOnMainThread(); }
void callOnMainThreadAndWait(MainThreadFunction* function, void* context) { ASSERT(function); if (isMainThread()) { function(context); return; } ThreadCondition syncFlag; Mutex& functionQueueMutex = mainThreadFunctionQueueMutex(); MutexLocker locker(functionQueueMutex); functionQueue().append(FunctionWithContext(function, context, &syncFlag)); if (functionQueue().size() == 1) scheduleDispatchFunctionsOnMainThread(); syncFlag.wait(functionQueueMutex); }
void cancelCallOnMainThread(MainThreadFunction* function, void* context) { ASSERT(function); std::lock_guard<std::mutex> lock(mainThreadFunctionQueueMutex()); FunctionWithContextFinder pred(FunctionWithContext(function, context)); while (true) { // We must redefine 'i' each pass, because the itererator's operator= // requires 'this' to be valid, and remove() invalidates all iterators FunctionQueue::iterator i(functionQueue().findIf(pred)); if (i == functionQueue().end()) break; functionQueue().remove(i); } }
void callOnMainThread(MainThreadFunction* function, void* context) { ASSERT(function); { MutexLocker locker(mainThreadFunctionQueueMutex()); functionQueue().append(FunctionWithContext(function, context)); } scheduleDispatchFunctionsOnMainThread(); }
void dispatchFunctionsFromMainThread() { ASSERT(isMainThread()); if (callbacksPaused) return; FunctionQueue queueCopy; { MutexLocker locker(mainThreadFunctionQueueMutex()); queueCopy.swap(functionQueue()); } for (unsigned i = 0; i < queueCopy.size(); ++i) { FunctionWithContext& invocation = queueCopy[i]; invocation.function(invocation.context); if (invocation.syncFlag) invocation.syncFlag->signal(); } }