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..1169ac5c25b2d69a359d28e2b607602ba2f882b0 100644 |
--- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp |
+++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp |
@@ -12,6 +12,7 @@ |
#include "modules/compositorworker/CompositorWorkerGlobalScope.h" |
#include "platform/ThreadSafeFunctional.h" |
#include "platform/TraceEvent.h" |
+#include "platform/WaitableEvent.h" |
#include "public/platform/Platform.h" |
namespace blink { |
@@ -19,33 +20,87 @@ 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() |
+ { |
+ MutexLocker locker(holderInstanceMutex()); |
kinuko
2016/05/23 09:53:55
I'd like to remove this lock if it shouldn't be ne
flackr
2016/05/25 16:42:52
Given s_instance is cleared on main after a synchr
|
+ if (!s_instance) |
+ s_instance = new BackingThreadHolder; |
+ } |
+ |
+ static void clear() |
{ |
- ASSERT(!m_thread || (m_thread->workerScriptCount() == 0)); |
- m_thread = nullptr; |
- m_thread = WorkerBackingThread::createForTest(Platform::current()->compositorThread()); |
+ MutexLocker locker(holderInstanceMutex()); |
+ if (s_instance) { |
+ s_instance->thread()->isolate()->TerminateExecution(); |
+ s_instance->shutdownAndWait(); |
+ delete s_instance; |
+ s_instance = nullptr; |
+ } |
} |
+ static void createForTest() |
+ { |
+ MutexLocker locker(holderInstanceMutex()); |
+ DCHECK_EQ(nullptr, s_instance); |
+ s_instance = new BackingThreadHolder(WorkerBackingThread::createForTest(Platform::current()->compositorThread())); |
flackr
2016/05/20 15:51:18
I didn't like how resetForTest swapped out the m_t
|
+ } |
+ |
+ WorkerBackingThread* thread() { return m_thread.get(); } |
+ |
private: |
- BackingThreadHolder() : m_thread(WorkerBackingThread::create(Platform::current()->compositorThread())) {} |
+ BackingThreadHolder(PassOwnPtr<WorkerBackingThread> useBackingThread = nullptr) |
+ : m_thread(useBackingThread ? useBackingThread.release() : WorkerBackingThread::create(Platform::current()->compositorThread())) |
+ { |
+ DCHECK(isMainThread()); |
+ Platform::current()->compositorThread()->getWebTaskRunner()->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() |
+ { |
+ DCHECK_EQ(0u, m_thread->workerScriptCount()) << "BackingThreadHolder should be the first to attach to WorkerBackingThread"; |
+ m_thread->attach(); |
+ } |
+ |
+ void shutdownAndWait() |
+ { |
+ DCHECK(isMainThread()); |
+ WaitableEvent doneEvent; |
+ Platform::current()->compositorThread()->getWebTaskRunner()->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; |
+ |
+ static BackingThreadHolder* s_instance; |
}; |
+BackingThreadHolder* BackingThreadHolder::s_instance = nullptr; |
+ |
} // namespace |
PassOwnPtr<CompositorWorkerThread> CompositorWorkerThread::create(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, InProcessWorkerObjectProxy& workerObjectProxy, double timeOrigin) |
@@ -77,9 +132,21 @@ 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::clearSharedBackingThread() |
+{ |
+ DCHECK(isMainThread()); |
+ BackingThreadHolder::clear(); |
+} |
+ |
+void CompositorWorkerThread::createSharedBackingThreadForTest() |
{ |
- BackingThreadHolder::instance().resetForTest(); |
+ BackingThreadHolder::createForTest(); |
} |
} // namespace blink |