Index: third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp |
diff --git a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp |
index 78f1ed6beb27b0a324c26fab5deda377eb353b22..2458e8af75c6f2bf7796ad32a3655d418342a5f8 100644 |
--- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp |
+++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp |
@@ -12,6 +12,8 @@ |
#include "modules/compositorworker/CompositorWorkerGlobalScope.h" |
#include "platform/ThreadSafeFunctional.h" |
#include "platform/TraceEvent.h" |
+#include "platform/WaitableEvent.h" |
+#include "platform/WebThreadSupportingGC.h" |
#include "public/platform/Platform.h" |
namespace blink { |
@@ -19,33 +21,99 @@ namespace blink { |
namespace { |
// This is a singleton class holding the compositor worker thread in this |
-// renderrer process. BackingThreadHolst::m_thread will never be cleared, |
-// but Oilpan and V8 are detached from the thread when the last compositor |
-// worker thread is gone. |
+// renderer process. BackingThreadHolder::m_thread is cleared by |
+// ModulesInitializer::shutdown. |
// See WorkerThread::terminateAndWaitForAllWorkers for the process shutdown |
// case. |
class BackingThreadHolder { |
public: |
static BackingThreadHolder& instance() |
{ |
- DEFINE_THREAD_SAFE_STATIC_LOCAL(BackingThreadHolder, holder, new BackingThreadHolder); |
- return holder; |
+ MutexLocker locker(holderInstanceMutex()); |
+ return *s_instance; |
} |
- WorkerBackingThread* thread() { return m_thread.get(); } |
- void resetForTest() |
+ static void ensureInstance() |
+ { |
+ if (!s_instance) |
+ s_instance = new BackingThreadHolder; |
+ } |
+ |
+ static void terminateExecution() |
+ { |
+ MutexLocker locker(holderInstanceMutex()); |
+ if (s_instance && s_instance->m_initialized) { |
+ s_instance->thread()->isolate()->TerminateExecution(); |
+ s_instance->m_terminatingExecution = true; |
+ } |
+ } |
+ |
+ static void clear() |
+ { |
+ MutexLocker locker(holderInstanceMutex()); |
+ if (s_instance) { |
+ DCHECK(!s_instance->m_initialized || s_instance->m_terminatingExecution); |
+ s_instance->shutdownAndWait(); |
+ delete s_instance; |
+ s_instance = nullptr; |
+ } |
+ } |
+ |
+ static void createForTest() |
{ |
- ASSERT(!m_thread || (m_thread->workerScriptCount() == 0)); |
- m_thread = nullptr; |
- m_thread = WorkerBackingThread::createForTest(Platform::current()->compositorThread()); |
+ MutexLocker locker(holderInstanceMutex()); |
+ DCHECK_EQ(nullptr, s_instance); |
+ s_instance = new BackingThreadHolder(WorkerBackingThread::createForTest(Platform::current()->compositorThread())); |
} |
+ WorkerBackingThread* thread() { return m_thread.get(); } |
+ |
private: |
- BackingThreadHolder() : m_thread(WorkerBackingThread::create(Platform::current()->compositorThread())) {} |
+ BackingThreadHolder(PassOwnPtr<WorkerBackingThread> useBackingThread = nullptr) |
+ : m_thread(useBackingThread ? std::move(useBackingThread) : WorkerBackingThread::create(Platform::current()->compositorThread())) |
+ { |
+ DCHECK(isMainThread()); |
+ m_thread->backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&BackingThreadHolder::initializeOnThread, AllowCrossThreadAccess(this))); |
+ } |
+ |
+ static Mutex& holderInstanceMutex() |
+ { |
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, holderMutex, new Mutex); |
+ return holderMutex; |
+ } |
+ |
+ void initializeOnThread() |
+ { |
+ MutexLocker locker(holderInstanceMutex()); |
+ DCHECK_EQ(0u, m_thread->workerScriptCount()) << "BackingThreadHolder should be the first to attach to WorkerBackingThread"; |
+ m_thread->attach(); |
+ m_initialized = true; |
+ } |
+ |
+ void shutdownAndWait() |
+ { |
+ DCHECK(isMainThread()); |
+ WaitableEvent doneEvent; |
+ m_thread->backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&BackingThreadHolder::shutdownOnThread, AllowCrossThreadAccess(this), AllowCrossThreadAccess(&doneEvent))); |
+ doneEvent.wait(); |
+ } |
+ |
+ void shutdownOnThread(WaitableEvent* doneEvent) |
+ { |
+ DCHECK_EQ(1u, m_thread->workerScriptCount()) << "BackingThreadHolder should be the last to detach from WorkerBackingThread"; |
+ m_thread->detach(); |
+ doneEvent->signal(); |
+ } |
OwnPtr<WorkerBackingThread> m_thread; |
+ bool m_terminatingExecution = false; |
+ bool m_initialized = false; |
+ |
+ static BackingThreadHolder* s_instance; |
}; |
+BackingThreadHolder* BackingThreadHolder::s_instance = nullptr; |
+ |
} // namespace |
PassOwnPtr<CompositorWorkerThread> CompositorWorkerThread::create(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, InProcessWorkerObjectProxy& workerObjectProxy, double timeOrigin) |
@@ -77,9 +145,27 @@ WorkerGlobalScope*CompositorWorkerThread::createWorkerGlobalScope(PassOwnPtr<Wor |
return CompositorWorkerGlobalScope::create(this, std::move(startupData), m_timeOrigin); |
} |
-void CompositorWorkerThread::resetSharedBackingThreadForTest() |
+void CompositorWorkerThread::ensureSharedBackingThread() |
+{ |
+ DCHECK(isMainThread()); |
+ BackingThreadHolder::ensureInstance(); |
+} |
+ |
+void CompositorWorkerThread::terminateExecution() |
+{ |
+ DCHECK(isMainThread()); |
+ BackingThreadHolder::terminateExecution(); |
+} |
+ |
+void CompositorWorkerThread::clearSharedBackingThread() |
+{ |
+ DCHECK(isMainThread()); |
+ BackingThreadHolder::clear(); |
+} |
+ |
+void CompositorWorkerThread::createSharedBackingThreadForTest() |
{ |
- BackingThreadHolder::instance().resetForTest(); |
+ BackingThreadHolder::createForTest(); |
} |
} // namespace blink |