Chromium Code Reviews| Index: third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.cpp |
| diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f17037007ab02a99bc136143c645d5593f6d7123 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.cpp |
| @@ -0,0 +1,169 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "modules/webaudio/AudioWorkletThread.h" |
| + |
| +#include "core/workers/WorkerBackingThread.h" |
| +#include "core/workers/WorkerThreadStartupData.h" |
| +#include "modules/webaudio/AudioWorkletGlobalScope.h" |
| +#include "platform/CrossThreadFunctional.h" |
| +#include "platform/TraceEvent.h" |
| +#include "platform/WaitableEvent.h" |
| +#include "platform/WebThreadSupportingGC.h" |
| +#include "platform/weborigin/SecurityOrigin.h" |
| +#include "public/platform/Platform.h" |
| +#include "wtf/Assertions.h" |
| +#include "wtf/PtrUtil.h" |
| +#include <memory> |
| + |
| +namespace blink { |
| + |
| +namespace { |
| + |
| + class BackingThreadHolder { |
|
haraken
2016/09/30 00:18:38
Can we share the implementation with BackingThread
haraken
2016/09/30 00:18:38
Redundant indentation.
hongchan
2016/10/11 23:42:38
Done.
|
| + public: |
| + static BackingThreadHolder* instance() |
| + { |
| + MutexLocker locker(holderInstanceMutex()); |
| + return s_instance; |
| + } |
| + |
| + static void ensureInstance() |
| + { |
| + if (!s_instance) |
| + s_instance = new BackingThreadHolder; |
| + } |
| + |
| + static void clear() |
| + { |
| + MutexLocker locker(holderInstanceMutex()); |
| + if (s_instance) { |
| + 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("AudioWorkletThread", BlinkGC::PerThreadHeapMode)); |
| + } |
| + |
| + WorkerBackingThread* thread() { return m_thread.get(); } |
| + |
| + private: |
| + BackingThreadHolder(std::unique_ptr<WorkerBackingThread> useBackingThread = nullptr) |
| + : m_thread(useBackingThread ? std::move(useBackingThread) : WorkerBackingThread::create("AudioWorkletThread", BlinkGC::PerThreadHeapMode)) |
| + { |
| + DCHECK(isMainThread()); |
| + m_thread->backingThread().postTask(BLINK_FROM_HERE, crossThreadBind(&BackingThreadHolder::initializeOnThread, crossThreadUnretained(this))); |
| + } |
| + |
| + static Mutex& holderInstanceMutex() |
| + { |
| + DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, holderMutex, new Mutex); |
| + return holderMutex; |
| + } |
| + |
| + void initializeOnThread() |
| + { |
| + MutexLocker locker(holderInstanceMutex()); |
| + DCHECK(!m_initialized); |
| + m_thread->initialize(); |
| + m_initialized = true; |
| + } |
| + |
| + void shutdownAndWait() |
| + { |
| + DCHECK(isMainThread()); |
| + WaitableEvent doneEvent; |
| + m_thread->backingThread().postTask(BLINK_FROM_HERE, crossThreadBind(&BackingThreadHolder::shutdownOnThread, crossThreadUnretained(this), crossThreadUnretained(&doneEvent))); |
| + doneEvent.wait(); |
| + } |
| + |
| + void shutdownOnThread(WaitableEvent* doneEvent) |
| + { |
| + m_thread->shutdown(); |
| + doneEvent->signal(); |
| + } |
| + |
| + std::unique_ptr<WorkerBackingThread> m_thread; |
| + bool m_initialized = false; |
| + |
| + static BackingThreadHolder* s_instance; |
| + }; |
| + |
| + BackingThreadHolder* BackingThreadHolder::s_instance = nullptr; |
| + |
| +} // namespace |
| + |
| +std::unique_ptr<AudioWorkletThread> AudioWorkletThread::create(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, WorkerReportingProxy& workerReportingProxy) |
| +{ |
| + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("audio-worklet"), "AudioWorkletThread::create"); |
| + DCHECK(isMainThread()); |
| + return wrapUnique(new AudioWorkletThread(std::move(workerLoaderProxy), workerReportingProxy)); |
| +} |
| + |
| +AudioWorkletThread::AudioWorkletThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, WorkerReportingProxy& workerReportingProxy) |
| + : WorkerThread(std::move(workerLoaderProxy), workerReportingProxy) |
| +{ |
| +} |
| + |
| +AudioWorkletThread::~AudioWorkletThread() |
| +{ |
| +} |
| + |
| +WorkerBackingThread& AudioWorkletThread::workerBackingThread() |
| +{ |
| + return *BackingThreadHolder::instance()->thread(); |
| +} |
| + |
| +void collectAllGarbageOnAudioWorkletThread(WaitableEvent* doneEvent) |
| +{ |
| + blink::ThreadState::current()->collectAllGarbage(); |
| + doneEvent->signal(); |
| +} |
| + |
| +void AudioWorkletThread::collectAllGarbage() |
| +{ |
| + DCHECK(isMainThread()); |
| + WaitableEvent doneEvent; |
| + BackingThreadHolder* instance = BackingThreadHolder::instance(); |
| + if (!instance) |
| + return; |
| + instance->thread()->backingThread().postTask(BLINK_FROM_HERE, crossThreadBind(&collectAllGarbageOnAudioWorkletThread, crossThreadUnretained(&doneEvent))); |
| + doneEvent.wait(); |
| +} |
| + |
| +void AudioWorkletThread::ensureSharedBackingThread() |
| +{ |
| + DCHECK(isMainThread()); |
| + BackingThreadHolder::ensureInstance(); |
| +} |
| + |
| +void AudioWorkletThread::clearSharedBackingThread() |
| +{ |
| + DCHECK(isMainThread()); |
| + BackingThreadHolder::clear(); |
| +} |
| + |
| +void AudioWorkletThread::createSharedBackingThreadForTest() |
| +{ |
| + BackingThreadHolder::createForTest(); |
| +} |
| + |
| +WorkerOrWorkletGlobalScope* AudioWorkletThread::createWorkerGlobalScope(std::unique_ptr<WorkerThreadStartupData> startupData) |
| +{ |
| + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("audio-worklet"), "AudioWorkletThread::createWorkerGlobalScope"); |
| + |
| + RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::create(startupData->m_scriptURL); |
| + if (startupData->m_starterOriginPrivilegeData) |
| + securityOrigin->transferPrivilegesFrom(std::move(startupData->m_starterOriginPrivilegeData)); |
| + |
| + return AudioWorkletGlobalScope::create(startupData->m_scriptURL, startupData->m_userAgent, securityOrigin.release(), this->isolate(), this); |
| +} |
| + |
| +} // namespace blink |