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

Side by Side Diff: third_party/WebKit/Source/core/workers/WorkerThread.cpp

Issue 1992933002: Introduce WorkletGlobalScopeProxy interface. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix tests. Created 4 years, 6 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
1 /* 1 /*
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 #include "platform/scheduler/CancellableTaskFactory.h" 46 #include "platform/scheduler/CancellableTaskFactory.h"
47 #include "platform/weborigin/KURL.h" 47 #include "platform/weborigin/KURL.h"
48 #include "public/platform/WebThread.h" 48 #include "public/platform/WebThread.h"
49 #include "wtf/Functional.h" 49 #include "wtf/Functional.h"
50 #include "wtf/Noncopyable.h" 50 #include "wtf/Noncopyable.h"
51 #include "wtf/text/WTFString.h" 51 #include "wtf/text/WTFString.h"
52 #include <limits.h> 52 #include <limits.h>
53 53
54 namespace blink { 54 namespace blink {
55 55
56 // TODO(nhiroki): Adjust the delay based on UMA. 56 class WorkerGlobalScopeFactory final : public WorkerOrWorkletThread::GlobalScope Factory {
57 const long long kForceTerminationDelayInMs = 2000; // 2 secs
58
59 // ForceTerminationTask is used for posting a delayed task to terminate the
60 // worker execution from the main thread. This task is expected to run when the
61 // shutdown sequence does not start in a certain time period because of an
62 // inifite loop in the JS execution context etc. When the shutdown sequence is
63 // started before this task runs, the task is simply cancelled.
64 class WorkerThread::ForceTerminationTask final {
65 public: 57 public:
66 static PassOwnPtr<ForceTerminationTask> create(WorkerThread* workerThread) 58 WorkerOrWorkletGlobalScope* create() const final
67 { 59 {
68 return adoptPtr(new ForceTerminationTask(workerThread)); 60 return m_workerThread.createWorkerGlobalScope(m_startupData.get());
69 } 61 }
70 62
71 void schedule() 63 WorkerGlobalScopeFactory(WorkerThread& workerThread, PassOwnPtr<WorkerThread StartupData> startupData)
72 { 64 : m_workerThread(workerThread)
73 DCHECK(isMainThread()); 65 , m_startupData(std::move(startupData)) { }
74 Platform::current()->mainThread()->getWebTaskRunner()->postDelayedTask(B LINK_FROM_HERE, m_cancellableTaskFactory->cancelAndCreate(), m_workerThread->m_f orceTerminationDelayInMs); 66 private:
75 }
76 67
77 private: 68 WorkerThread& m_workerThread;
78 explicit ForceTerminationTask(WorkerThread* workerThread) 69 OwnPtr<WorkerThreadStartupData> m_startupData;
79 : m_workerThread(workerThread)
80 {
81 DCHECK(isMainThread());
82 m_cancellableTaskFactory = CancellableTaskFactory::create(this, &ForceTe rminationTask::run);
83 }
84
85 void run()
86 {
87 DCHECK(isMainThread());
88 MutexLocker lock(m_workerThread->m_threadStateMutex);
89 if (m_workerThread->m_readyToShutdown) {
90 // Shutdown sequence is now running. Just return.
91 return;
92 }
93
94 m_workerThread->forciblyTerminateExecution();
95 DCHECK_EQ(WorkerThread::ExitCode::NotTerminated, m_workerThread->m_exitC ode);
96 m_workerThread->m_exitCode = WorkerThread::ExitCode::AsyncForciblyTermin ated;
97 }
98
99 WorkerThread* m_workerThread;
100 OwnPtr<CancellableTaskFactory> m_cancellableTaskFactory;
101 }; 70 };
102 71
103 class WorkerThread::WorkerMicrotaskRunner final : public WebThread::TaskObserver {
104 public:
105 explicit WorkerMicrotaskRunner(WorkerThread* workerThread)
106 : m_workerThread(workerThread)
107 {
108 }
109
110 void willProcessTask() override
111 {
112 // No tasks should get executed after we have closed.
113 DCHECK(!m_workerThread->workerGlobalScope() || !m_workerThread->workerGl obalScope()->isClosing());
114 }
115
116 void didProcessTask() override
117 {
118 Microtask::performCheckpoint(m_workerThread->isolate());
119 if (WorkerGlobalScope* globalScope = m_workerThread->workerGlobalScope() ) {
120 if (WorkerOrWorkletScriptController* scriptController = globalScope- >scriptController())
121 scriptController->getRejectedPromises()->processQueue();
122 if (globalScope->isClosing()) {
123 // |m_workerThread| will eventually be requested to terminate.
124 m_workerThread->workerReportingProxy().workerGlobalScopeClosed() ;
125
126 // Stop further worker tasks to run after this point.
127 m_workerThread->prepareForShutdownOnWorkerThread();
128 }
129 }
130 }
131
132 private:
133 // Thread owns the microtask runner; reference remains
134 // valid for the lifetime of this object.
135 WorkerThread* m_workerThread;
136 };
137
138 static Mutex& threadSetMutex()
139 {
140 DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, new Mutex);
141 return mutex;
142 }
143
144 static HashSet<WorkerThread*>& workerThreads()
145 {
146 DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ());
147 return threads;
148 }
149
150 WorkerThread::~WorkerThread()
151 {
152 DCHECK(isMainThread());
153 MutexLocker lock(threadSetMutex());
154 DCHECK(workerThreads().contains(this));
155 workerThreads().remove(this);
156
157 // TODO(nhiroki): Record how this thread is terminated (i.e. m_exitCode)
158 // in UMA.
159 DCHECK_NE(ExitCode::NotTerminated, m_exitCode);
160 }
161
162 void WorkerThread::start(PassOwnPtr<WorkerThreadStartupData> startupData) 72 void WorkerThread::start(PassOwnPtr<WorkerThreadStartupData> startupData)
163 { 73 {
164 DCHECK(isMainThread()); 74 DCHECK(isMainThread());
165 75
166 if (m_started) 76 if (m_started)
167 return; 77 return;
168 78
169 m_started = true; 79 m_started = true;
170 workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBi nd(&WorkerThread::initializeOnWorkerThread, AllowCrossThreadAccess(this), passed (std::move(startupData)))); 80 workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBi nd(&WorkerThread::initializeOnWorkerThread, AllowCrossThreadAccess(this), passed (std::move(startupData))));
171 } 81 }
172 82
173 void WorkerThread::terminate() 83 WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, Work erReportingProxy& workerReportingProxy)
84 : WorkerOrWorkletThread(workerReportingProxy)
85 , m_workerLoaderProxy(workerLoaderProxy)
174 { 86 {
175 DCHECK(isMainThread());
176 terminateInternal(TerminationMode::Graceful);
177 }
178
179 void WorkerThread::terminateAndWait()
180 {
181 DCHECK(isMainThread());
182
183 // The main thread will be blocked, so asynchronous graceful shutdown does
184 // not work.
185 terminateInternal(TerminationMode::Forcible);
186 m_shutdownEvent->wait();
187 }
188
189 void WorkerThread::terminateAndWaitForAllWorkers()
190 {
191 DCHECK(isMainThread());
192
193 // Keep this lock to prevent WorkerThread instances from being destroyed.
194 MutexLocker lock(threadSetMutex());
195 HashSet<WorkerThread*> threads = workerThreads();
196
197 // The main thread will be blocked, so asynchronous graceful shutdown does
198 // not work.
199 for (WorkerThread* thread : threads)
200 thread->terminateInternal(TerminationMode::Forcible);
201
202 for (WorkerThread* thread : threads)
203 thread->m_shutdownEvent->wait();
204 }
205
206 v8::Isolate* WorkerThread::isolate()
207 {
208 return workerBackingThread().isolate();
209 }
210
211 bool WorkerThread::isCurrentThread()
212 {
213 return m_started && workerBackingThread().backingThread().isCurrentThread();
214 }
215
216 void WorkerThread::postTask(const WebTraceLocation& location, std::unique_ptr<Ex ecutionContextTask> task)
217 {
218 workerBackingThread().backingThread().postTask(location, createWorkerThreadT ask(std::move(task), true));
219 }
220
221 void WorkerThread::appendDebuggerTask(std::unique_ptr<CrossThreadClosure> task)
222 {
223 {
224 MutexLocker lock(m_threadStateMutex);
225 if (m_readyToShutdown)
226 return;
227 }
228 m_inspectorTaskRunner->appendTask(threadSafeBind(&WorkerThread::runDebuggerT askOnWorkerThread, AllowCrossThreadAccess(this), passed(std::move(task))));
229 {
230 MutexLocker lock(m_threadStateMutex);
231 if (isolate())
232 m_inspectorTaskRunner->interruptAndRunAllTasksDontWait(isolate());
233 }
234 workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBi nd(&WorkerThread::runDebuggerTaskDontWaitOnWorkerThread, AllowCrossThreadAccess( this)));
235 }
236
237 void WorkerThread::startRunningDebuggerTasksOnPause()
238 {
239 m_pausedInDebugger = true;
240 ThreadDebugger::idleStarted(isolate());
241 std::unique_ptr<CrossThreadClosure> task;
242 do {
243 {
244 SafePointScope safePointScope(BlinkGC::HeapPointersOnStack);
245 task = m_inspectorTaskRunner->takeNextTask(InspectorTaskRunner::Wait ForTask);
246 }
247 if (task)
248 (*task)();
249 // Keep waiting until execution is resumed.
250 } while (task && m_pausedInDebugger);
251 ThreadDebugger::idleFinished(isolate());
252 }
253
254 void WorkerThread::stopRunningDebuggerTasksOnPause()
255 {
256 m_pausedInDebugger = false;
257 }
258
259 WorkerGlobalScope* WorkerThread::workerGlobalScope()
260 {
261 DCHECK(isCurrentThread());
262 return m_workerGlobalScope.get();
263 }
264
265 bool WorkerThread::terminated()
266 {
267 MutexLocker lock(m_threadStateMutex);
268 return m_terminated;
269 }
270
271 unsigned WorkerThread::workerThreadCount()
272 {
273 MutexLocker lock(threadSetMutex());
274 return workerThreads().size();
275 }
276
277 PlatformThreadId WorkerThread::platformThreadId()
278 {
279 if (!m_started)
280 return 0;
281 return workerBackingThread().backingThread().platformThread().threadId();
282 }
283
284 WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, Work erReportingProxy& workerReportingProxy)
285 : m_forceTerminationDelayInMs(kForceTerminationDelayInMs)
286 , m_inspectorTaskRunner(adoptPtr(new InspectorTaskRunner()))
287 , m_workerLoaderProxy(workerLoaderProxy)
288 , m_workerReportingProxy(workerReportingProxy)
289 , m_terminationEvent(adoptPtr(new WaitableEvent(
290 WaitableEvent::ResetPolicy::Manual,
291 WaitableEvent::InitialState::NonSignaled)))
292 , m_shutdownEvent(adoptPtr(new WaitableEvent(
293 WaitableEvent::ResetPolicy::Manual,
294 WaitableEvent::InitialState::NonSignaled)))
295 {
296 MutexLocker lock(threadSetMutex());
297 workerThreads().add(this);
298 }
299
300 std::unique_ptr<CrossThreadClosure> WorkerThread::createWorkerThreadTask(std::un ique_ptr<ExecutionContextTask> task, bool isInstrumented)
301 {
302 if (isInstrumented)
303 isInstrumented = !task->taskNameForInstrumentation().isEmpty();
304 if (isInstrumented) {
305 DCHECK(isCurrentThread());
306 InspectorInstrumentation::asyncTaskScheduled(workerGlobalScope(), "Worke r task", task.get());
307 }
308 return threadSafeBind(&WorkerThread::performTaskOnWorkerThread, AllowCrossTh readAccess(this), passed(std::move(task)), isInstrumented);
309 }
310
311 void WorkerThread::terminateInternal(TerminationMode mode)
312 {
313 DCHECK(m_started);
314
315 // Prevent the deadlock between GC and an attempt to terminate a thread.
316 SafePointScope safePointScope(BlinkGC::HeapPointersOnStack);
317
318 // Protect against this method, initializeOnWorkerThread() or termination
319 // via the global scope racing each other.
320 MutexLocker lock(m_threadStateMutex);
321
322 // If terminate has already been called.
323 if (m_terminated) {
324 // The synchronous forcible termination request should overtake the
325 // scheduled termination task because the request will block the main
326 // thread and the scheduled termination task never runs.
327 if (mode == TerminationMode::Forcible && m_exitCode == ExitCode::NotTerm inated) {
328 DCHECK(m_scheduledForceTerminationTask);
329 m_scheduledForceTerminationTask.reset();
330 forciblyTerminateExecution();
331 DCHECK_EQ(ExitCode::NotTerminated, m_exitCode);
332 m_exitCode = ExitCode::SyncForciblyTerminated;
333 }
334 return;
335 }
336 m_terminated = true;
337
338 // Signal the thread to notify that the thread's stopping.
339 if (m_terminationEvent)
340 m_terminationEvent->signal();
341
342 // If the worker thread was never initialized, don't start another
343 // shutdown, but still wait for the thread to signal when shutdown has
344 // completed on initializeOnWorkerThread().
345 if (!m_workerGlobalScope) {
346 DCHECK_EQ(ExitCode::NotTerminated, m_exitCode);
347 m_exitCode = ExitCode::GracefullyTerminated;
348 return;
349 }
350
351 // Determine if we should synchronously terminate or schedule to terminate
352 // the worker execution so that the task can be handled by thread event
353 // loop. If script execution weren't forbidden, a while(1) loop in JS could
354 // keep the thread alive forever.
355 //
356 // (1) |m_readyToShutdown|: It this is set, the worker thread has already
357 // noticed that the thread is about to be terminated and the worker global
358 // scope is already disposed, so we don't have to explicitly terminate the
359 // worker execution.
360 //
361 // (2) |workerScriptCount() == 1|: If other WorkerGlobalScopes are running
362 // on the worker thread, we should not terminate the worker execution. This
363 // condition is not entirely correct because other scripts can be being
364 // initialized or terminated simuletaneously. Though this function itself is
365 // protected by a mutex, it is possible that |workerScriptCount()| here is
366 // not consistent with that in |initialize| and |shutdown|.
367 //
368 // (3) |m_runningDebuggerTask|: Terminating during debugger task may lead to
369 // crash due to heavy use of v8 api in debugger. Any debugger task is
370 // guaranteed to finish, so we can wait for the completion.
371 bool shouldScheduleToTerminateExecution = !m_readyToShutdown && (workerBacki ngThread().workerScriptCount() == 1) && !m_runningDebuggerTask;
372
373 if (shouldScheduleToTerminateExecution) {
374 if (mode == TerminationMode::Forcible) {
375 forciblyTerminateExecution();
376 DCHECK_EQ(ExitCode::NotTerminated, m_exitCode);
377 m_exitCode = ExitCode::SyncForciblyTerminated;
378 } else {
379 DCHECK_EQ(TerminationMode::Graceful, mode);
380 DCHECK(!m_scheduledForceTerminationTask);
381 m_scheduledForceTerminationTask = ForceTerminationTask::create(this) ;
382 m_scheduledForceTerminationTask->schedule();
383 }
384 }
385
386 m_inspectorTaskRunner->kill();
387 workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBi nd(&WorkerThread::prepareForShutdownOnWorkerThread, AllowCrossThreadAccess(this) ));
388 workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBi nd(&WorkerThread::performShutdownOnWorkerThread, AllowCrossThreadAccess(this)));
389 }
390
391 void WorkerThread::forciblyTerminateExecution()
392 {
393 DCHECK(m_workerGlobalScope);
394 m_workerGlobalScope->scriptController()->willScheduleExecutionTermination();
395 isolate()->TerminateExecution();
396 } 87 }
397 88
398 void WorkerThread::initializeOnWorkerThread(PassOwnPtr<WorkerThreadStartupData> startupData) 89 void WorkerThread::initializeOnWorkerThread(PassOwnPtr<WorkerThreadStartupData> startupData)
399 { 90 {
400 KURL scriptURL = startupData->m_scriptURL; 91 KURL scriptURL = startupData->m_scriptURL;
401 String sourceCode = startupData->m_sourceCode; 92 String sourceCode = startupData->m_sourceCode;
402 WorkerThreadStartMode startMode = startupData->m_startMode; 93 WorkerThreadStartMode startMode = startupData->m_startMode;
403 OwnPtr<Vector<char>> cachedMetaData = std::move(startupData->m_cachedMetaDat a); 94 OwnPtr<Vector<char>> cachedMetaData = std::move(startupData->m_cachedMetaDat a);
404 V8CacheOptions v8CacheOptions = startupData->m_v8CacheOptions; 95 V8CacheOptions v8CacheOptions = startupData->m_v8CacheOptions;
405 96
406 { 97 WorkerGlobalScopeFactory factory(*this, std::move(startupData));
407 MutexLocker lock(m_threadStateMutex); 98 initializeGlobalScope(factory);
99 if (m_terminated)
100 return;
408 101
409 // The worker was terminated before the thread had a chance to run. 102 toWorkerGlobalScope(globalScope())->scriptLoaded(sourceCode.length(), cached MetaData.get() ? cachedMetaData->size() : 0);
410 if (m_terminated) {
411 DCHECK_EQ(ExitCode::GracefullyTerminated, m_exitCode);
412
413 // Notify the proxy that the WorkerGlobalScope has been disposed of.
414 // This can free this thread object, hence it must not be touched
415 // afterwards.
416 m_workerReportingProxy.workerThreadTerminated();
417
418 // Notify the main thread that it is safe to deallocate our
419 // resources.
420 m_shutdownEvent->signal();
421 return;
422 }
423
424 workerBackingThread().attach();
425
426 if (shouldAttachThreadDebugger())
427 V8PerIsolateData::from(isolate())->setThreadDebugger(adoptPtr(new Wo rkerThreadDebugger(this, isolate())));
428 m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this));
429 workerBackingThread().backingThread().addTaskObserver(m_microtaskRunner. get());
430
431 // Optimize for memory usage instead of latency for the worker isolate.
432 isolate()->IsolateInBackgroundNotification();
433 m_workerGlobalScope = createWorkerGlobalScope(std::move(startupData));
434 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge t() ? cachedMetaData->size() : 0);
435
436 // Notify proxy that a new WorkerGlobalScope has been created and starte d.
437 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get( ));
438
439 WorkerOrWorkletScriptController* scriptController = m_workerGlobalScope- >scriptController();
440 if (!scriptController->isExecutionForbidden()) {
441 scriptController->initializeContextIfNeeded();
442
443 // If Origin Trials have been registered before the V8 context was r eady,
444 // then inject them into the context now
445 ExecutionContext* executionContext = m_workerGlobalScope->getExecuti onContext();
446 if (executionContext) {
447 OriginTrialContext* originTrialContext = OriginTrialContext::fro m(executionContext);
448 if (originTrialContext)
449 originTrialContext->initializePendingFeatures();
450 }
451 }
452 }
453 103
454 if (startMode == PauseWorkerGlobalScopeOnStart) 104 if (startMode == PauseWorkerGlobalScopeOnStart)
455 startRunningDebuggerTasksOnPause(); 105 startRunningDebuggerTasksOnPause();
456 106
457 if (m_workerGlobalScope->scriptController()->isContextInitialized()) { 107 CachedMetadataHandler* handler = toWorkerGlobalScope(globalScope())->createW orkerScriptCachedMetadataHandler(scriptURL, cachedMetaData.get());
458 m_workerReportingProxy.didInitializeWorkerContext(); 108 bool success = globalScope()->scriptController()->evaluate(ScriptSourceCode( sourceCode, scriptURL), nullptr, handler, v8CacheOptions);
459 v8::HandleScope handleScope(isolate()); 109 toWorkerGlobalScope(globalScope())->didEvaluateWorkerScript();
460 Platform::current()->workerContextCreated(m_workerGlobalScope->scriptCon troller()->context()); 110 workerReportingProxy().didEvaluateWorkerScript(success);
461 }
462
463 CachedMetadataHandler* handler = workerGlobalScope()->createWorkerScriptCach edMetadataHandler(scriptURL, cachedMetaData.get());
464 bool success = m_workerGlobalScope->scriptController()->evaluate(ScriptSourc eCode(sourceCode, scriptURL), nullptr, handler, v8CacheOptions);
465 m_workerGlobalScope->didEvaluateWorkerScript();
466 m_workerReportingProxy.didEvaluateWorkerScript(success);
467 111
468 postInitialize(); 112 postInitialize();
469 } 113 }
470 114
471 void WorkerThread::prepareForShutdownOnWorkerThread()
472 {
473 DCHECK(isCurrentThread());
474 {
475 MutexLocker lock(m_threadStateMutex);
476 if (m_readyToShutdown)
477 return;
478 m_readyToShutdown = true;
479 if (m_exitCode == ExitCode::NotTerminated)
480 m_exitCode = ExitCode::GracefullyTerminated;
481 }
482
483 workerReportingProxy().willDestroyWorkerGlobalScope();
484 InspectorInstrumentation::allAsyncTasksCanceled(workerGlobalScope());
485 workerGlobalScope()->dispose();
486 workerBackingThread().backingThread().removeTaskObserver(m_microtaskRunner.g et());
487 }
488
489 void WorkerThread::performShutdownOnWorkerThread()
490 {
491 DCHECK(isCurrentThread());
492 #if DCHECK_IS_ON
493 {
494 MutexLocker lock(m_threadStateMutex);
495 DCHECK(m_terminated);
496 DCHECK(m_readyToShutdown);
497 }
498 #endif
499
500 // The below assignment will destroy the context, which will in turn notify
501 // messaging proxy. We cannot let any objects survive past thread exit,
502 // because no other thread will run GC or otherwise destroy them. If Oilpan
503 // is enabled, we detach of the context/global scope, with the final heap
504 // cleanup below sweeping it out.
505 m_workerGlobalScope->notifyContextDestroyed();
506 m_workerGlobalScope = nullptr;
507
508 workerBackingThread().detach();
509 // We must not touch workerBackingThread() from now on.
510
511 m_microtaskRunner = nullptr;
512
513 // Notify the proxy that the WorkerGlobalScope has been disposed of.
514 // This can free this thread object, hence it must not be touched
515 // afterwards.
516 workerReportingProxy().workerThreadTerminated();
517
518 m_shutdownEvent->signal();
519 }
520
521 void WorkerThread::performTaskOnWorkerThread(std::unique_ptr<ExecutionContextTas k> task, bool isInstrumented)
522 {
523 DCHECK(isCurrentThread());
524 {
525 MutexLocker lock(m_threadStateMutex);
526 if (m_readyToShutdown)
527 return;
528 }
529
530 WorkerGlobalScope* globalScope = workerGlobalScope();
531 // If the thread is terminated before it had a chance initialize (see
532 // WorkerThread::Initialize()), we mustn't run any of the posted tasks.
533 if (!globalScope) {
534 DCHECK(terminated());
535 return;
536 }
537
538 InspectorInstrumentation::AsyncTask asyncTask(globalScope, task.get(), isIns trumented);
539 task->performTask(globalScope);
540 }
541
542 void WorkerThread::runDebuggerTaskOnWorkerThread(std::unique_ptr<CrossThreadClos ure> task)
543 {
544 DCHECK(isCurrentThread());
545 InspectorTaskRunner::IgnoreInterruptsScope scope(m_inspectorTaskRunner.get() );
546 {
547 MutexLocker lock(m_threadStateMutex);
548 m_runningDebuggerTask = true;
549 }
550 ThreadDebugger::idleFinished(isolate());
551 (*task)();
552 ThreadDebugger::idleStarted(isolate());
553 {
554 MutexLocker lock(m_threadStateMutex);
555 m_runningDebuggerTask = false;
556
557 if (!m_terminated)
558 return;
559 // terminate() was called. Shutdown sequence will start soon.
560 }
561 // Stop further worker tasks to run after this point.
562 prepareForShutdownOnWorkerThread();
563 }
564
565 void WorkerThread::runDebuggerTaskDontWaitOnWorkerThread()
566 {
567 DCHECK(isCurrentThread());
568 std::unique_ptr<CrossThreadClosure> task = m_inspectorTaskRunner->takeNextTa sk(InspectorTaskRunner::DontWaitForTask);
569 if (task)
570 (*task)();
571 }
572
573 WorkerThread::ExitCode WorkerThread::getExitCode()
574 {
575 MutexLocker lock(m_threadStateMutex);
576 return m_exitCode;
577 }
578
579 } // namespace blink 115 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/workers/WorkerThread.h ('k') | third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698