Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.cpp

Issue 1978063002: [DO NOT SUBMIT] AudioWorklet FS2a: AudioWorkletThread on OfflineAudioContext (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@FS2-audiorendersink-audioworkletthread
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "modules/webaudio/AudioWorkletThread.h"
6
7 #include "bindings/core/v8/Microtask.h"
8 #include "bindings/core/v8/ScriptSourceCode.h"
9 #include "bindings/core/v8/V8Binding.h"
10 #include "bindings/core/v8/V8GCController.h"
11 #include "bindings/core/v8/V8Initializer.h"
12 #include "bindings/core/v8/V8PerIsolateData.h"
13 #include "bindings/core/v8/WorkerOrWorkletScriptController.h"
14 #include "core/events/MessageEvent.h"
15 #include "modules/webaudio/AudioDestinationNode.h"
16 #include "modules/webaudio/AudioWorkletGlobalScope.h"
17 #include "modules/webaudio/AudioWorkletThreadStartupData.h"
18 #include "platform/Logging.h"
19 #include "platform/Task.h"
20 #include "platform/ThreadSafeFunctional.h"
21 #include "platform/WebThreadSupportingGC.h"
22 #include "public/platform/Platform.h"
23 #include "public/platform/WebThread.h"
24
25 namespace blink {
26
27 namespace {
28
29 class WorkletMicrotaskRunner : public WebThread::TaskObserver {
30
31 public:
32 explicit WorkletMicrotaskRunner(AudioWorkletThread* audioWorkletThread)
33 : m_audioWorkletThread(audioWorkletThread)
34 {
35 }
36
37 void willProcessTask() final {}
38
39 void didProcessTask() final
40 {
41 Microtask::performCheckpoint(m_audioWorkletThread->isolate());
42 }
43
44 private:
45 // Thread owns the microtask runner; reference remains
46 // valid for the lifetime of this object.
47 AudioWorkletThread* m_audioWorkletThread;
48 };
49
50 void destroyThread(WebThreadSupportingGC* thread)
51 {
52 ASSERT(isMainThread());
53 // The destructor for |thread| will block until all tasks have completed .
54 // This guarantees that shutdown will finish before the thread is destro yed.
55 delete thread;
56 }
57
58 class AudioWorkletSharedState {
59 public:
60 static AudioWorkletSharedState& instance()
61 {
62 DEFINE_THREAD_SAFE_STATIC_LOCAL(AudioWorkletSharedState, audioWorkle tSharedState, (new AudioWorkletSharedState()));
63 return audioWorkletSharedState;
64 }
65
66 WebThreadSupportingGC* audioWorkletThread()
67 {
68 MutexLocker lock(m_mutex);
69 if (!m_thread && isMainThread()) {
70 ASSERT(!m_workerCount);
71 WebThread* platformThread = Platform::current()->createThread("o ffline audio renderer");
72 m_thread = WebThreadSupportingGC::createForThread(platformThread );
73 }
74 return m_thread.get();
75 }
76
77 void initializeBackingThread()
78 {
79 MutexLocker lock(m_mutex);
80 ASSERT(m_thread->isCurrentThread());
81
82 // ++m_workerCount;
83 // if (m_workerCount > 1)
84 // return;
85
86 m_thread->initialize();
87
88 // Initialize the isolate at the same time.
89 ASSERT(!m_isolate);
90 m_isolate = V8PerIsolateData::initialize();
91 V8Initializer::initializeWorker(m_isolate);
92
93 // OwnPtr<V8IsolateInterruptor> interruptor = adoptPtr(new V8Isolate Interruptor(m_isolate));
94 // ThreadState::current()->addInterruptor(interruptor.release());
95 // ThreadState::current()->registerTraceDOMWrappers(m_isolate, V8GCC ontroller::traceDOMWrappers);
96 }
97
98 void shutdownBackingThread()
99 {
100 MutexLocker lock(m_mutex);
101 ASSERT(m_thread->isCurrentThread());
102
103 // ASSERT(m_workerCount > 0);
104 // --m_workerCount;
105
106 if (m_workerCount == 0) {
107 m_thread->shutdown();
108 Platform::current()->mainThread()->getWebTaskRunner()->postTask(
109 BLINK_FROM_HERE, threadSafeBind(destroyThread, AllowCrossThr eadAccess(m_thread.leakPtr())));
110 }
111 }
112
113 v8::Isolate* isolate()
114 {
115 MutexLocker lock(m_mutex);
116 ASSERT(m_thread->isCurrentThread());
117 ASSERT(m_isolate);
118 // It is safe to use the existing isolate even if TerminateExecution () has been
119 // called on it, without calling CancelTerminateExecution().
120 return m_isolate;
121 }
122
123 void willDestroyIsolate()
124 {
125 MutexLocker lock(m_mutex);
126 ASSERT(m_thread->isCurrentThread());
127 if (m_workerCount == 1)
128 V8PerIsolateData::willBeDestroyed(m_isolate);
129 }
130
131 void destroyIsolate()
132 {
133 MutexLocker lock(m_mutex);
134 if (!m_thread) {
135 ASSERT(m_workerCount == 0);
136 V8PerIsolateData::destroy(m_isolate);
137 m_isolate = nullptr;
138 }
139 }
140
141 void terminateV8Execution()
142 {
143 MutexLocker lock(m_mutex);
144 ASSERT(isMainThread());
145 if (m_workerCount > 1)
146 return;
147 m_isolate->TerminateExecution();
148 }
149
150 private:
151 AudioWorkletSharedState() {}
152 ~AudioWorkletSharedState() {}
153 Mutex m_mutex;
154 OwnPtr<WebThreadSupportingGC> m_thread;
155 int m_workerCount = 0;
156 v8::Isolate* m_isolate = nullptr;
157 };
158
159 } // namespace
160
161 PassRefPtr<AudioWorkletThread> AudioWorkletThread::create(AudioDestinationHandle r& audioDestinationHandler)
162 {
163 ASSERT(isMainThread());
164 return adoptRef(new AudioWorkletThread(audioDestinationHandler));
165 }
166
167 AudioWorkletThread::AudioWorkletThread(AudioDestinationHandler& audioDestination Handler)
168 : m_destinationHandler(audioDestinationHandler)
169 {
170 }
171
172 AudioWorkletThread::~AudioWorkletThread()
173 {
174 }
175
176 bool AudioWorkletThread::isCurrentThread()
177 {
178 return audioRenderThread().isCurrentThread();
179 }
180
181 void AudioWorkletThread::initialize(LocalFrame* frame, PassOwnPtr<AudioWorkletTh readStartupData> startupData)
182 {
183 ASSERT(isMainThread());
184
185 if (m_initialized)
186 return;
187
188 m_initialized = true;
189 audioRenderThread().postTask(BLINK_FROM_HERE, threadSafeBind(&AudioWorkletTh read::initializeInternal, AllowCrossThreadAccess(this), frame, passed(std::move( startupData))));
hongchan 2016/05/23 21:48:54 In file included from ../../third_party/WebKit/Sou
190 }
191
192 void AudioWorkletThread::initializeInternal(LocalFrame* frame, PassOwnPtr<AudioW orkletThreadStartupData> startupData)
193 {
194 ASSERT(audioRenderThread().isCurrentThread());
195 {
196 MutexLocker lock(m_threadStateMutex);
197 m_microtaskRunner = adoptPtr(new WorkletMicrotaskRunner(this));
198 AudioWorkletSharedState::instance().initializeBackingThread();
199 audioRenderThread().addTaskObserver(m_microtaskRunner.get());
200 m_isolate = AudioWorkletSharedState::instance().isolate();
201 m_audioWorkletGlobalScope = AudioWorkletGlobalScope::create(frame, start upData->m_url, startupData->m_userAgent, startupData->m_securityOrigin.release() , m_isolate);
202 }
203 }
204
205 void AudioWorkletThread::shutdown()
206 {
207 ASSERT(isMainThread());
208 m_audioWorkletGlobalScope->scriptController()->willScheduleExecutionTerminat ion();
209 AudioWorkletSharedState::instance().terminateV8Execution();
210 audioRenderThread().postTask(BLINK_FROM_HERE, threadSafeBind(&AudioWorkletTh read::shutdownInternal, AllowCrossThreadAccess(this)));
211 }
212
213 void AudioWorkletThread::evaluate(const String& sourceCode, const KURL& scriptUR L)
214 {
215 ASSERT(isMainThread());
216 audioRenderThread().postTask(BLINK_FROM_HERE, threadSafeBind(&AudioWorkletTh read::evaluateInternal, AllowCrossThreadAccess(this), sourceCode.isolatedCopy(), scriptURL.copy()));
217 }
218
219 void AudioWorkletThread::evaluateInternal(const String& sourceCode, const KURL& scriptURL)
220 {
221 ASSERT(audioRenderThread().isCurrentThread());
222 m_audioWorkletGlobalScope->scriptController()->evaluate(ScriptSourceCode(sou rceCode, scriptURL));
223 }
224
225 WebThreadSupportingGC& AudioWorkletThread::audioRenderThread()
226 {
227 return *AudioWorkletSharedState::instance().audioWorkletThread();
228 }
229
230 void AudioWorkletThread::shutdownInternal()
231 {
232 ASSERT(isCurrentThread());
233 {
234 MutexLocker lock(m_threadStateMutex);
235 if (m_shutdown)
236 return;
237 m_shutdown = true;
238 }
239 m_audioWorkletGlobalScope->dispose();
240 audioRenderThread().postTask(BLINK_FROM_HERE, threadSafeBind(&AudioWorkletTh read::performShutdownTask, AllowCrossThreadAccess(this)));
241 }
242
243 void AudioWorkletThread::performShutdownTask()
244 {
245 // The below assignment will destroy the context, which will in turn notify mess aging proxy.
246 // We cannot let any objects survive past thread exit, because no other thread w ill run GC or otherwise destroy them.
247 // If Oilpan is enabled, we detach of the context/global scope, with the final h eap cleanup below sweeping it out.
248 #if !ENABLE(OILPAN)
249 ASSERT(m_audioWorkletGlobalScope->hasOneRef());
250 #endif
251 m_audioWorkletGlobalScope->notifyContextDestroyed();
252 m_audioWorkletGlobalScope = nullptr;
253 AudioWorkletSharedState::instance().willDestroyIsolate();
254 AudioWorkletSharedState::instance().shutdownBackingThread();
255 AudioWorkletSharedState::instance().terminateV8Execution();
256 m_isolate = nullptr;
257 m_microtaskRunner = nullptr;
258 // Notify the proxy that the WorkerGlobalScope has been disposed of.
259 // This can free this thread object, hence it must not be touched afterwards .
260 m_destinationHandler.stopRendering();
261 }
262 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698