| Index: third_party/WebKit/Source/core/workers/WorkerThread.cpp
|
| diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.cpp b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
|
| index 62c4fd888ac86f03869271c109be5607ccb159c8..38b458b6e1a7a9567f52f48b40ae76d464169e2c 100644
|
| --- a/third_party/WebKit/Source/core/workers/WorkerThread.cpp
|
| +++ b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
|
| @@ -53,111 +53,21 @@
|
|
|
| namespace blink {
|
|
|
| -// TODO(nhiroki): Adjust the delay based on UMA.
|
| -const long long kForceTerminationDelayInMs = 2000; // 2 secs
|
| -
|
| -// ForceTerminationTask is used for posting a delayed task to terminate the
|
| -// worker execution from the main thread. This task is expected to run when the
|
| -// shutdown sequence does not start in a certain time period because of an
|
| -// inifite loop in the JS execution context etc. When the shutdown sequence is
|
| -// started before this task runs, the task is simply cancelled.
|
| -class WorkerThread::ForceTerminationTask final {
|
| +class WorkerGlobalScopeFactory final : public WorkerOrWorkletThread::GlobalScopeFactory {
|
| public:
|
| - static PassOwnPtr<ForceTerminationTask> create(WorkerThread* workerThread)
|
| - {
|
| - return adoptPtr(new ForceTerminationTask(workerThread));
|
| - }
|
| -
|
| - void schedule()
|
| + WorkerOrWorkletGlobalScope* create() const final
|
| {
|
| - DCHECK(isMainThread());
|
| - Platform::current()->mainThread()->getWebTaskRunner()->postDelayedTask(BLINK_FROM_HERE, m_cancellableTaskFactory->cancelAndCreate(), m_workerThread->m_forceTerminationDelayInMs);
|
| + return m_workerThread.createWorkerGlobalScope(m_startupData.get());
|
| }
|
|
|
| -private:
|
| - explicit ForceTerminationTask(WorkerThread* workerThread)
|
| + WorkerGlobalScopeFactory(WorkerThread& workerThread, PassOwnPtr<WorkerThreadStartupData> startupData)
|
| : m_workerThread(workerThread)
|
| - {
|
| - DCHECK(isMainThread());
|
| - m_cancellableTaskFactory = CancellableTaskFactory::create(this, &ForceTerminationTask::run);
|
| - }
|
| -
|
| - void run()
|
| - {
|
| - DCHECK(isMainThread());
|
| - MutexLocker lock(m_workerThread->m_threadStateMutex);
|
| - if (m_workerThread->m_readyToShutdown) {
|
| - // Shutdown sequence is now running. Just return.
|
| - return;
|
| - }
|
| -
|
| - m_workerThread->forciblyTerminateExecution();
|
| - DCHECK_EQ(WorkerThread::ExitCode::NotTerminated, m_workerThread->m_exitCode);
|
| - m_workerThread->m_exitCode = WorkerThread::ExitCode::AsyncForciblyTerminated;
|
| - }
|
| -
|
| - WorkerThread* m_workerThread;
|
| - OwnPtr<CancellableTaskFactory> m_cancellableTaskFactory;
|
| -};
|
| -
|
| -class WorkerThread::WorkerMicrotaskRunner final : public WebThread::TaskObserver {
|
| -public:
|
| - explicit WorkerMicrotaskRunner(WorkerThread* workerThread)
|
| - : m_workerThread(workerThread)
|
| - {
|
| - }
|
| -
|
| - void willProcessTask() override
|
| - {
|
| - // No tasks should get executed after we have closed.
|
| - DCHECK(!m_workerThread->workerGlobalScope() || !m_workerThread->workerGlobalScope()->isClosing());
|
| - }
|
| -
|
| - void didProcessTask() override
|
| - {
|
| - Microtask::performCheckpoint(m_workerThread->isolate());
|
| - if (WorkerGlobalScope* globalScope = m_workerThread->workerGlobalScope()) {
|
| - if (WorkerOrWorkletScriptController* scriptController = globalScope->scriptController())
|
| - scriptController->getRejectedPromises()->processQueue();
|
| - if (globalScope->isClosing()) {
|
| - // |m_workerThread| will eventually be requested to terminate.
|
| - m_workerThread->workerReportingProxy().workerGlobalScopeClosed();
|
| -
|
| - // Stop further worker tasks to run after this point.
|
| - m_workerThread->prepareForShutdownOnWorkerThread();
|
| - }
|
| - }
|
| - }
|
| -
|
| + , m_startupData(std::move(startupData)) { }
|
| private:
|
| - // Thread owns the microtask runner; reference remains
|
| - // valid for the lifetime of this object.
|
| - WorkerThread* m_workerThread;
|
| -};
|
| -
|
| -static Mutex& threadSetMutex()
|
| -{
|
| - DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, new Mutex);
|
| - return mutex;
|
| -}
|
| -
|
| -static HashSet<WorkerThread*>& workerThreads()
|
| -{
|
| - DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ());
|
| - return threads;
|
| -}
|
| -
|
| -WorkerThread::~WorkerThread()
|
| -{
|
| - DCHECK(isMainThread());
|
| - MutexLocker lock(threadSetMutex());
|
| - DCHECK(workerThreads().contains(this));
|
| - workerThreads().remove(this);
|
|
|
| - // TODO(nhiroki): Record how this thread is terminated (i.e. m_exitCode)
|
| - // in UMA.
|
| - DCHECK_NE(ExitCode::NotTerminated, m_exitCode);
|
| -}
|
| + WorkerThread& m_workerThread;
|
| + OwnPtr<WorkerThreadStartupData> m_startupData;
|
| +};
|
|
|
| void WorkerThread::start(PassOwnPtr<WorkerThreadStartupData> startupData)
|
| {
|
| @@ -170,229 +80,10 @@ void WorkerThread::start(PassOwnPtr<WorkerThreadStartupData> startupData)
|
| workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&WorkerThread::initializeOnWorkerThread, AllowCrossThreadAccess(this), passed(std::move(startupData))));
|
| }
|
|
|
| -void WorkerThread::terminate()
|
| -{
|
| - DCHECK(isMainThread());
|
| - terminateInternal(TerminationMode::Graceful);
|
| -}
|
| -
|
| -void WorkerThread::terminateAndWait()
|
| -{
|
| - DCHECK(isMainThread());
|
| -
|
| - // The main thread will be blocked, so asynchronous graceful shutdown does
|
| - // not work.
|
| - terminateInternal(TerminationMode::Forcible);
|
| - m_shutdownEvent->wait();
|
| -}
|
| -
|
| -void WorkerThread::terminateAndWaitForAllWorkers()
|
| -{
|
| - DCHECK(isMainThread());
|
| -
|
| - // Keep this lock to prevent WorkerThread instances from being destroyed.
|
| - MutexLocker lock(threadSetMutex());
|
| - HashSet<WorkerThread*> threads = workerThreads();
|
| -
|
| - // The main thread will be blocked, so asynchronous graceful shutdown does
|
| - // not work.
|
| - for (WorkerThread* thread : threads)
|
| - thread->terminateInternal(TerminationMode::Forcible);
|
| -
|
| - for (WorkerThread* thread : threads)
|
| - thread->m_shutdownEvent->wait();
|
| -}
|
| -
|
| -v8::Isolate* WorkerThread::isolate()
|
| -{
|
| - return workerBackingThread().isolate();
|
| -}
|
| -
|
| -bool WorkerThread::isCurrentThread()
|
| -{
|
| - return m_started && workerBackingThread().backingThread().isCurrentThread();
|
| -}
|
| -
|
| -void WorkerThread::postTask(const WebTraceLocation& location, std::unique_ptr<ExecutionContextTask> task)
|
| -{
|
| - workerBackingThread().backingThread().postTask(location, createWorkerThreadTask(std::move(task), true));
|
| -}
|
| -
|
| -void WorkerThread::appendDebuggerTask(std::unique_ptr<CrossThreadClosure> task)
|
| -{
|
| - {
|
| - MutexLocker lock(m_threadStateMutex);
|
| - if (m_readyToShutdown)
|
| - return;
|
| - }
|
| - m_inspectorTaskRunner->appendTask(threadSafeBind(&WorkerThread::runDebuggerTaskOnWorkerThread, AllowCrossThreadAccess(this), passed(std::move(task))));
|
| - {
|
| - MutexLocker lock(m_threadStateMutex);
|
| - if (isolate())
|
| - m_inspectorTaskRunner->interruptAndRunAllTasksDontWait(isolate());
|
| - }
|
| - workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&WorkerThread::runDebuggerTaskDontWaitOnWorkerThread, AllowCrossThreadAccess(this)));
|
| -}
|
| -
|
| -void WorkerThread::startRunningDebuggerTasksOnPause()
|
| -{
|
| - m_pausedInDebugger = true;
|
| - ThreadDebugger::idleStarted(isolate());
|
| - std::unique_ptr<CrossThreadClosure> task;
|
| - do {
|
| - {
|
| - SafePointScope safePointScope(BlinkGC::HeapPointersOnStack);
|
| - task = m_inspectorTaskRunner->takeNextTask(InspectorTaskRunner::WaitForTask);
|
| - }
|
| - if (task)
|
| - (*task)();
|
| - // Keep waiting until execution is resumed.
|
| - } while (task && m_pausedInDebugger);
|
| - ThreadDebugger::idleFinished(isolate());
|
| -}
|
| -
|
| -void WorkerThread::stopRunningDebuggerTasksOnPause()
|
| -{
|
| - m_pausedInDebugger = false;
|
| -}
|
| -
|
| -WorkerGlobalScope* WorkerThread::workerGlobalScope()
|
| -{
|
| - DCHECK(isCurrentThread());
|
| - return m_workerGlobalScope.get();
|
| -}
|
| -
|
| -bool WorkerThread::terminated()
|
| -{
|
| - MutexLocker lock(m_threadStateMutex);
|
| - return m_terminated;
|
| -}
|
| -
|
| -unsigned WorkerThread::workerThreadCount()
|
| -{
|
| - MutexLocker lock(threadSetMutex());
|
| - return workerThreads().size();
|
| -}
|
| -
|
| -PlatformThreadId WorkerThread::platformThreadId()
|
| -{
|
| - if (!m_started)
|
| - return 0;
|
| - return workerBackingThread().backingThread().platformThread().threadId();
|
| -}
|
| -
|
| WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, WorkerReportingProxy& workerReportingProxy)
|
| - : m_forceTerminationDelayInMs(kForceTerminationDelayInMs)
|
| - , m_inspectorTaskRunner(adoptPtr(new InspectorTaskRunner()))
|
| + : WorkerOrWorkletThread(workerReportingProxy)
|
| , m_workerLoaderProxy(workerLoaderProxy)
|
| - , m_workerReportingProxy(workerReportingProxy)
|
| - , m_terminationEvent(adoptPtr(new WaitableEvent(
|
| - WaitableEvent::ResetPolicy::Manual,
|
| - WaitableEvent::InitialState::NonSignaled)))
|
| - , m_shutdownEvent(adoptPtr(new WaitableEvent(
|
| - WaitableEvent::ResetPolicy::Manual,
|
| - WaitableEvent::InitialState::NonSignaled)))
|
| {
|
| - MutexLocker lock(threadSetMutex());
|
| - workerThreads().add(this);
|
| -}
|
| -
|
| -std::unique_ptr<CrossThreadClosure> WorkerThread::createWorkerThreadTask(std::unique_ptr<ExecutionContextTask> task, bool isInstrumented)
|
| -{
|
| - if (isInstrumented)
|
| - isInstrumented = !task->taskNameForInstrumentation().isEmpty();
|
| - if (isInstrumented) {
|
| - DCHECK(isCurrentThread());
|
| - InspectorInstrumentation::asyncTaskScheduled(workerGlobalScope(), "Worker task", task.get());
|
| - }
|
| - return threadSafeBind(&WorkerThread::performTaskOnWorkerThread, AllowCrossThreadAccess(this), passed(std::move(task)), isInstrumented);
|
| -}
|
| -
|
| -void WorkerThread::terminateInternal(TerminationMode mode)
|
| -{
|
| - DCHECK(m_started);
|
| -
|
| - // Prevent the deadlock between GC and an attempt to terminate a thread.
|
| - SafePointScope safePointScope(BlinkGC::HeapPointersOnStack);
|
| -
|
| - // Protect against this method, initializeOnWorkerThread() or termination
|
| - // via the global scope racing each other.
|
| - MutexLocker lock(m_threadStateMutex);
|
| -
|
| - // If terminate has already been called.
|
| - if (m_terminated) {
|
| - // The synchronous forcible termination request should overtake the
|
| - // scheduled termination task because the request will block the main
|
| - // thread and the scheduled termination task never runs.
|
| - if (mode == TerminationMode::Forcible && m_exitCode == ExitCode::NotTerminated) {
|
| - DCHECK(m_scheduledForceTerminationTask);
|
| - m_scheduledForceTerminationTask.reset();
|
| - forciblyTerminateExecution();
|
| - DCHECK_EQ(ExitCode::NotTerminated, m_exitCode);
|
| - m_exitCode = ExitCode::SyncForciblyTerminated;
|
| - }
|
| - return;
|
| - }
|
| - m_terminated = true;
|
| -
|
| - // Signal the thread to notify that the thread's stopping.
|
| - if (m_terminationEvent)
|
| - m_terminationEvent->signal();
|
| -
|
| - // If the worker thread was never initialized, don't start another
|
| - // shutdown, but still wait for the thread to signal when shutdown has
|
| - // completed on initializeOnWorkerThread().
|
| - if (!m_workerGlobalScope) {
|
| - DCHECK_EQ(ExitCode::NotTerminated, m_exitCode);
|
| - m_exitCode = ExitCode::GracefullyTerminated;
|
| - return;
|
| - }
|
| -
|
| - // Determine if we should synchronously terminate or schedule to terminate
|
| - // the worker execution so that the task can be handled by thread event
|
| - // loop. If script execution weren't forbidden, a while(1) loop in JS could
|
| - // keep the thread alive forever.
|
| - //
|
| - // (1) |m_readyToShutdown|: It this is set, the worker thread has already
|
| - // noticed that the thread is about to be terminated and the worker global
|
| - // scope is already disposed, so we don't have to explicitly terminate the
|
| - // worker execution.
|
| - //
|
| - // (2) |workerScriptCount() == 1|: If other WorkerGlobalScopes are running
|
| - // on the worker thread, we should not terminate the worker execution. This
|
| - // condition is not entirely correct because other scripts can be being
|
| - // initialized or terminated simuletaneously. Though this function itself is
|
| - // protected by a mutex, it is possible that |workerScriptCount()| here is
|
| - // not consistent with that in |initialize| and |shutdown|.
|
| - //
|
| - // (3) |m_runningDebuggerTask|: Terminating during debugger task may lead to
|
| - // crash due to heavy use of v8 api in debugger. Any debugger task is
|
| - // guaranteed to finish, so we can wait for the completion.
|
| - bool shouldScheduleToTerminateExecution = !m_readyToShutdown && (workerBackingThread().workerScriptCount() == 1) && !m_runningDebuggerTask;
|
| -
|
| - if (shouldScheduleToTerminateExecution) {
|
| - if (mode == TerminationMode::Forcible) {
|
| - forciblyTerminateExecution();
|
| - DCHECK_EQ(ExitCode::NotTerminated, m_exitCode);
|
| - m_exitCode = ExitCode::SyncForciblyTerminated;
|
| - } else {
|
| - DCHECK_EQ(TerminationMode::Graceful, mode);
|
| - DCHECK(!m_scheduledForceTerminationTask);
|
| - m_scheduledForceTerminationTask = ForceTerminationTask::create(this);
|
| - m_scheduledForceTerminationTask->schedule();
|
| - }
|
| - }
|
| -
|
| - m_inspectorTaskRunner->kill();
|
| - workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&WorkerThread::prepareForShutdownOnWorkerThread, AllowCrossThreadAccess(this)));
|
| - workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&WorkerThread::performShutdownOnWorkerThread, AllowCrossThreadAccess(this)));
|
| -}
|
| -
|
| -void WorkerThread::forciblyTerminateExecution()
|
| -{
|
| - DCHECK(m_workerGlobalScope);
|
| - m_workerGlobalScope->scriptController()->willScheduleExecutionTermination();
|
| - isolate()->TerminateExecution();
|
| }
|
|
|
| void WorkerThread::initializeOnWorkerThread(PassOwnPtr<WorkerThreadStartupData> startupData)
|
| @@ -403,177 +94,22 @@ void WorkerThread::initializeOnWorkerThread(PassOwnPtr<WorkerThreadStartupData>
|
| OwnPtr<Vector<char>> cachedMetaData = std::move(startupData->m_cachedMetaData);
|
| V8CacheOptions v8CacheOptions = startupData->m_v8CacheOptions;
|
|
|
| - {
|
| - MutexLocker lock(m_threadStateMutex);
|
| -
|
| - // The worker was terminated before the thread had a chance to run.
|
| - if (m_terminated) {
|
| - DCHECK_EQ(ExitCode::GracefullyTerminated, m_exitCode);
|
| -
|
| - // Notify the proxy that the WorkerGlobalScope has been disposed of.
|
| - // This can free this thread object, hence it must not be touched
|
| - // afterwards.
|
| - m_workerReportingProxy.workerThreadTerminated();
|
| -
|
| - // Notify the main thread that it is safe to deallocate our
|
| - // resources.
|
| - m_shutdownEvent->signal();
|
| - return;
|
| - }
|
| -
|
| - workerBackingThread().attach();
|
| -
|
| - if (shouldAttachThreadDebugger())
|
| - V8PerIsolateData::from(isolate())->setThreadDebugger(adoptPtr(new WorkerThreadDebugger(this, isolate())));
|
| - m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this));
|
| - workerBackingThread().backingThread().addTaskObserver(m_microtaskRunner.get());
|
| -
|
| - // Optimize for memory usage instead of latency for the worker isolate.
|
| - isolate()->IsolateInBackgroundNotification();
|
| - m_workerGlobalScope = createWorkerGlobalScope(std::move(startupData));
|
| - m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.get() ? cachedMetaData->size() : 0);
|
| -
|
| - // Notify proxy that a new WorkerGlobalScope has been created and started.
|
| - m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get());
|
| + WorkerGlobalScopeFactory factory(*this, std::move(startupData));
|
| + initializeGlobalScope(factory);
|
| + if (m_terminated)
|
| + return;
|
|
|
| - WorkerOrWorkletScriptController* scriptController = m_workerGlobalScope->scriptController();
|
| - if (!scriptController->isExecutionForbidden()) {
|
| - scriptController->initializeContextIfNeeded();
|
| -
|
| - // If Origin Trials have been registered before the V8 context was ready,
|
| - // then inject them into the context now
|
| - ExecutionContext* executionContext = m_workerGlobalScope->getExecutionContext();
|
| - if (executionContext) {
|
| - OriginTrialContext* originTrialContext = OriginTrialContext::from(executionContext);
|
| - if (originTrialContext)
|
| - originTrialContext->initializePendingFeatures();
|
| - }
|
| - }
|
| - }
|
| + toWorkerGlobalScope(globalScope())->scriptLoaded(sourceCode.length(), cachedMetaData.get() ? cachedMetaData->size() : 0);
|
|
|
| if (startMode == PauseWorkerGlobalScopeOnStart)
|
| startRunningDebuggerTasksOnPause();
|
|
|
| - if (m_workerGlobalScope->scriptController()->isContextInitialized()) {
|
| - m_workerReportingProxy.didInitializeWorkerContext();
|
| - v8::HandleScope handleScope(isolate());
|
| - Platform::current()->workerContextCreated(m_workerGlobalScope->scriptController()->context());
|
| - }
|
| -
|
| - CachedMetadataHandler* handler = workerGlobalScope()->createWorkerScriptCachedMetadataHandler(scriptURL, cachedMetaData.get());
|
| - bool success = m_workerGlobalScope->scriptController()->evaluate(ScriptSourceCode(sourceCode, scriptURL), nullptr, handler, v8CacheOptions);
|
| - m_workerGlobalScope->didEvaluateWorkerScript();
|
| - m_workerReportingProxy.didEvaluateWorkerScript(success);
|
| + CachedMetadataHandler* handler = toWorkerGlobalScope(globalScope())->createWorkerScriptCachedMetadataHandler(scriptURL, cachedMetaData.get());
|
| + bool success = globalScope()->scriptController()->evaluate(ScriptSourceCode(sourceCode, scriptURL), nullptr, handler, v8CacheOptions);
|
| + toWorkerGlobalScope(globalScope())->didEvaluateWorkerScript();
|
| + workerReportingProxy().didEvaluateWorkerScript(success);
|
|
|
| postInitialize();
|
| }
|
|
|
| -void WorkerThread::prepareForShutdownOnWorkerThread()
|
| -{
|
| - DCHECK(isCurrentThread());
|
| - {
|
| - MutexLocker lock(m_threadStateMutex);
|
| - if (m_readyToShutdown)
|
| - return;
|
| - m_readyToShutdown = true;
|
| - if (m_exitCode == ExitCode::NotTerminated)
|
| - m_exitCode = ExitCode::GracefullyTerminated;
|
| - }
|
| -
|
| - workerReportingProxy().willDestroyWorkerGlobalScope();
|
| - InspectorInstrumentation::allAsyncTasksCanceled(workerGlobalScope());
|
| - workerGlobalScope()->dispose();
|
| - workerBackingThread().backingThread().removeTaskObserver(m_microtaskRunner.get());
|
| -}
|
| -
|
| -void WorkerThread::performShutdownOnWorkerThread()
|
| -{
|
| - DCHECK(isCurrentThread());
|
| -#if DCHECK_IS_ON
|
| - {
|
| - MutexLocker lock(m_threadStateMutex);
|
| - DCHECK(m_terminated);
|
| - DCHECK(m_readyToShutdown);
|
| - }
|
| -#endif
|
| -
|
| - // The below assignment will destroy the context, which will in turn notify
|
| - // messaging proxy. We cannot let any objects survive past thread exit,
|
| - // because no other thread will run GC or otherwise destroy them. If Oilpan
|
| - // is enabled, we detach of the context/global scope, with the final heap
|
| - // cleanup below sweeping it out.
|
| - m_workerGlobalScope->notifyContextDestroyed();
|
| - m_workerGlobalScope = nullptr;
|
| -
|
| - workerBackingThread().detach();
|
| - // We must not touch workerBackingThread() from now on.
|
| -
|
| - m_microtaskRunner = nullptr;
|
| -
|
| - // Notify the proxy that the WorkerGlobalScope has been disposed of.
|
| - // This can free this thread object, hence it must not be touched
|
| - // afterwards.
|
| - workerReportingProxy().workerThreadTerminated();
|
| -
|
| - m_shutdownEvent->signal();
|
| -}
|
| -
|
| -void WorkerThread::performTaskOnWorkerThread(std::unique_ptr<ExecutionContextTask> task, bool isInstrumented)
|
| -{
|
| - DCHECK(isCurrentThread());
|
| - {
|
| - MutexLocker lock(m_threadStateMutex);
|
| - if (m_readyToShutdown)
|
| - return;
|
| - }
|
| -
|
| - WorkerGlobalScope* globalScope = workerGlobalScope();
|
| - // If the thread is terminated before it had a chance initialize (see
|
| - // WorkerThread::Initialize()), we mustn't run any of the posted tasks.
|
| - if (!globalScope) {
|
| - DCHECK(terminated());
|
| - return;
|
| - }
|
| -
|
| - InspectorInstrumentation::AsyncTask asyncTask(globalScope, task.get(), isInstrumented);
|
| - task->performTask(globalScope);
|
| -}
|
| -
|
| -void WorkerThread::runDebuggerTaskOnWorkerThread(std::unique_ptr<CrossThreadClosure> task)
|
| -{
|
| - DCHECK(isCurrentThread());
|
| - InspectorTaskRunner::IgnoreInterruptsScope scope(m_inspectorTaskRunner.get());
|
| - {
|
| - MutexLocker lock(m_threadStateMutex);
|
| - m_runningDebuggerTask = true;
|
| - }
|
| - ThreadDebugger::idleFinished(isolate());
|
| - (*task)();
|
| - ThreadDebugger::idleStarted(isolate());
|
| - {
|
| - MutexLocker lock(m_threadStateMutex);
|
| - m_runningDebuggerTask = false;
|
| -
|
| - if (!m_terminated)
|
| - return;
|
| - // terminate() was called. Shutdown sequence will start soon.
|
| - }
|
| - // Stop further worker tasks to run after this point.
|
| - prepareForShutdownOnWorkerThread();
|
| -}
|
| -
|
| -void WorkerThread::runDebuggerTaskDontWaitOnWorkerThread()
|
| -{
|
| - DCHECK(isCurrentThread());
|
| - std::unique_ptr<CrossThreadClosure> task = m_inspectorTaskRunner->takeNextTask(InspectorTaskRunner::DontWaitForTask);
|
| - if (task)
|
| - (*task)();
|
| -}
|
| -
|
| -WorkerThread::ExitCode WorkerThread::getExitCode()
|
| -{
|
| - MutexLocker lock(m_threadStateMutex);
|
| - return m_exitCode;
|
| -}
|
| -
|
| } // namespace blink
|
|
|