diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WTF/wtf/MainThread.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WTF/wtf/MainThread.cpp')
-rw-r--r-- | Source/WTF/wtf/MainThread.cpp | 180 |
1 files changed, 65 insertions, 115 deletions
diff --git a/Source/WTF/wtf/MainThread.cpp b/Source/WTF/wtf/MainThread.cpp index b3d63d49e..eea0b36cd 100644 --- a/Source/WTF/wtf/MainThread.cpp +++ b/Source/WTF/wtf/MainThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -31,82 +31,36 @@ #include "CurrentTime.h" #include "Deque.h" -#include "Functional.h" #include "StdLibExtras.h" +#include "Threading.h" #include <mutex> +#include <wtf/Lock.h> #include <wtf/NeverDestroyed.h> #include <wtf/ThreadSpecific.h> namespace WTF { -struct FunctionWithContext { - MainThreadFunction* function; - void* context; - - FunctionWithContext(MainThreadFunction* function = nullptr, void* context = nullptr) - : function(function) - , context(context) - { - } - bool operator == (const FunctionWithContext& o) - { - return function == o.function && context == o.context; - } -}; - -class FunctionWithContextFinder { -public: - FunctionWithContextFinder(const FunctionWithContext& m) : m(m) {} - bool operator() (FunctionWithContext& o) { return o == m; } - FunctionWithContext m; -}; - - -typedef Deque<FunctionWithContext> FunctionQueue; - static bool callbacksPaused; // This global variable is only accessed from main thread. -#if !PLATFORM(MAC) +#if !OS(DARWIN) && !PLATFORM(GTK) static ThreadIdentifier mainThreadIdentifier; #endif -static std::mutex& mainThreadFunctionQueueMutex() -{ - static NeverDestroyed<std::mutex> mutex; - - return mutex; -} +static StaticLock mainThreadFunctionQueueMutex; -static FunctionQueue& functionQueue() +static Deque<Function<void ()>>& functionQueue() { - static NeverDestroyed<FunctionQueue> functionQueue; + static NeverDestroyed<Deque<Function<void ()>>> functionQueue; return functionQueue; } - -#if !PLATFORM(MAC) - -void initializeMainThread() -{ - static bool initializedMainThread; - if (initializedMainThread) - return; - initializedMainThread = true; - - mainThreadIdentifier = currentThread(); - - mainThreadFunctionQueueMutex(); - initializeMainThreadPlatform(); - initializeGCThreads(); -} - -#else - +#if OS(DARWIN) || PLATFORM(GTK) static pthread_once_t initializeMainThreadKeyOnce = PTHREAD_ONCE_INIT; static void initializeMainThreadOnce() { - mainThreadFunctionQueueMutex(); + initializeThreading(); initializeMainThreadPlatform(); + initializeGCThreads(); } void initializeMainThread() @@ -114,18 +68,19 @@ void initializeMainThread() pthread_once(&initializeMainThreadKeyOnce, initializeMainThreadOnce); } -#if !USE(WEB_THREAD) +#if !USE(WEB_THREAD) && !PLATFORM(GTK) static void initializeMainThreadToProcessMainThreadOnce() { - mainThreadFunctionQueueMutex(); + initializeThreading(); initializeMainThreadToProcessMainThreadPlatform(); + initializeGCThreads(); } void initializeMainThreadToProcessMainThread() { pthread_once(&initializeMainThreadKeyOnce, initializeMainThreadToProcessMainThreadOnce); } -#else +#elif !PLATFORM(GTK) static pthread_once_t initializeWebThreadKeyOnce = PTHREAD_ONCE_INIT; static void initializeWebThreadOnce() @@ -139,10 +94,24 @@ void initializeWebThread() } #endif // !USE(WEB_THREAD) +#else +void initializeMainThread() +{ + static bool initializedMainThread; + if (initializedMainThread) + return; + initializedMainThread = true; + + initializeThreading(); + mainThreadIdentifier = currentThread(); + + initializeMainThreadPlatform(); + initializeGCThreads(); +} #endif // 0.1 sec delays in UI is approximate threshold when they become noticeable. Have a limit that's half of that. -static const double maxRunLoopSuspensionTime = 0.05; +static const auto maxRunLoopSuspensionTime = std::chrono::milliseconds(50); void dispatchFunctionsFromMainThread() { @@ -151,72 +120,51 @@ void dispatchFunctionsFromMainThread() if (callbacksPaused) return; - double startTime = monotonicallyIncreasingTime(); + auto startTime = std::chrono::steady_clock::now(); + + Function<void ()> function; - FunctionWithContext invocation; while (true) { { - std::lock_guard<std::mutex> lock(mainThreadFunctionQueueMutex()); + std::lock_guard<StaticLock> lock(mainThreadFunctionQueueMutex); if (!functionQueue().size()) break; - invocation = functionQueue().takeFirst(); + + function = functionQueue().takeFirst(); } - invocation.function(invocation.context); + function(); + + // Clearing the function can have side effects, so do so outside of the lock above. + function = nullptr; // 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 (monotonicallyIncreasingTime() - startTime > maxRunLoopSuspensionTime) { + if (std::chrono::steady_clock::now() - startTime > maxRunLoopSuspensionTime) { scheduleDispatchFunctionsOnMainThread(); break; } } } -void callOnMainThread(MainThreadFunction* function, void* context) +void callOnMainThread(Function<void ()>&& function) { ASSERT(function); + bool needToSchedule = false; + { - std::lock_guard<std::mutex> lock(mainThreadFunctionQueueMutex()); + std::lock_guard<StaticLock> lock(mainThreadFunctionQueueMutex); needToSchedule = functionQueue().size() == 0; - functionQueue().append(FunctionWithContext(function, context)); + functionQueue().append(WTFMove(function)); } + if (needToSchedule) scheduleDispatchFunctionsOnMainThread(); } -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); - } -} - -static void callFunctionObject(void* context) -{ - auto function = std::unique_ptr<std::function<void ()>>(static_cast<std::function<void ()>*>(context)); - (*function)(); -} - -void callOnMainThread(std::function<void ()> function) -{ - callOnMainThread(callFunctionObject, std::make_unique<std::function<void ()>>(std::move(function)).release()); -} - void setMainThreadCallbacksPaused(bool paused) { ASSERT(isMainThread()); @@ -230,7 +178,7 @@ void setMainThreadCallbacksPaused(bool paused) scheduleDispatchFunctionsOnMainThread(); } -#if !PLATFORM(MAC) +#if !OS(DARWIN) && !PLATFORM(GTK) bool isMainThread() { return currentThread() == mainThreadIdentifier; @@ -244,19 +192,19 @@ bool canAccessThreadLocalDataForThread(ThreadIdentifier threadId) } #endif -#if ENABLE(PARALLEL_GC) -static ThreadSpecific<bool>* isGCThread; -#endif +static ThreadSpecific<std::optional<GCThreadType>, CanBeGCThread::True>* isGCThread; void initializeGCThreads() { -#if ENABLE(PARALLEL_GC) - isGCThread = new ThreadSpecific<bool>(); -#endif + static std::once_flag flag; + std::call_once( + flag, + [] { + isGCThread = new ThreadSpecific<std::optional<GCThreadType>, CanBeGCThread::True>(); + }); } -#if ENABLE(PARALLEL_GC) -void registerGCThread() +void registerGCThread(GCThreadType type) { if (!isGCThread) { // This happens if we're running in a process that doesn't care about @@ -264,22 +212,24 @@ void registerGCThread() return; } - **isGCThread = true; + **isGCThread = type; } bool isMainThreadOrGCThread() { - if (isGCThread->isSet() && **isGCThread) + if (mayBeGCThread()) return true; return isMainThread(); } -#elif PLATFORM(MAC) -// This is necessary because JavaScriptCore.exp doesn't support preprocessor macros. -bool isMainThreadOrGCThread() + +std::optional<GCThreadType> mayBeGCThread() { - return isMainThread(); + if (!isGCThread) + return std::nullopt; + if (!isGCThread->isSet()) + return std::nullopt; + return **isGCThread; } -#endif } // namespace WTF |