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

Unified Diff: Source/core/workers/WorkerRunLoop.cpp

Issue 432673003: Revert of Change WokerThread to use a blink::WebThread (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/workers/WorkerRunLoop.h ('k') | Source/core/workers/WorkerThread.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/workers/WorkerRunLoop.cpp
diff --git a/Source/core/workers/WorkerRunLoop.cpp b/Source/core/workers/WorkerRunLoop.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..39fdffd42566cfbe8764c935281747f57dd0e879
--- /dev/null
+++ b/Source/core/workers/WorkerRunLoop.cpp
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/workers/WorkerRunLoop.h"
+
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/workers/WorkerGlobalScope.h"
+#include "core/workers/WorkerThread.h"
+#include "platform/PlatformThreadData.h"
+#include "platform/SharedTimer.h"
+#include "platform/ThreadTimers.h"
+#include "platform/heap/ThreadState.h"
+#include "wtf/CurrentTime.h"
+
+namespace blink {
+
+class WorkerRunLoopTask : public blink::WebThread::Task {
+ WTF_MAKE_NONCOPYABLE(WorkerRunLoopTask); WTF_MAKE_FAST_ALLOCATED;
+public:
+ static PassOwnPtr<WorkerRunLoopTask> create(const WorkerRunLoop& runLoop, PassOwnPtr<ExecutionContextTask> task, bool isInstrumented)
+ {
+ return adoptPtr(new WorkerRunLoopTask(runLoop, task, isInstrumented));
+ }
+
+ virtual ~WorkerRunLoopTask() { }
+
+ virtual void run() OVERRIDE
+ {
+ WorkerGlobalScope* workerGlobalScope = m_runLoop.context();
+ if (m_isInstrumented)
+ InspectorInstrumentation::willPerformExecutionContextTask(workerGlobalScope, m_task.get());
+ if ((!workerGlobalScope->isClosing() && !m_runLoop.terminated()) || m_task->isCleanupTask())
+ m_task->performTask(workerGlobalScope);
+ if (m_isInstrumented)
+ InspectorInstrumentation::didPerformExecutionContextTask(workerGlobalScope);
+ }
+
+private:
+ WorkerRunLoopTask(const WorkerRunLoop& runLoop, PassOwnPtr<ExecutionContextTask> task, bool isInstrumented)
+ : m_runLoop(runLoop)
+ , m_task(task)
+ , m_isInstrumented(isInstrumented)
+ {
+ if (m_isInstrumented)
+ m_isInstrumented = !m_task->taskNameForInstrumentation().isEmpty();
+ if (m_isInstrumented)
+ InspectorInstrumentation::didPostExecutionContextTask(m_runLoop.context(), m_task.get());
+ }
+
+ const WorkerRunLoop& m_runLoop;
+ OwnPtr<ExecutionContextTask> m_task;
+ bool m_isInstrumented;
+};
+
+class TickleDebuggerQueueTask FINAL : public ExecutionContextTask {
+public:
+ static PassOwnPtr<TickleDebuggerQueueTask> create(WorkerRunLoop* loop)
+ {
+ return adoptPtr(new TickleDebuggerQueueTask(loop));
+ }
+ virtual void performTask(ExecutionContext* context) OVERRIDE
+ {
+ ASSERT(context->isWorkerGlobalScope());
+ m_loop->runDebuggerTask(WorkerRunLoop::DontWaitForMessage);
+ }
+
+private:
+ explicit TickleDebuggerQueueTask(WorkerRunLoop* loop) : m_loop(loop) { }
+
+ WorkerRunLoop* m_loop;
+};
+
+class WorkerSharedTimer : public SharedTimer {
+public:
+ WorkerSharedTimer()
+ : m_sharedTimerFunction(0)
+ , m_nextFireTime(0)
+ {
+ }
+
+ // SharedTimer interface.
+ virtual void setFiredFunction(void (*function)()) { m_sharedTimerFunction = function; }
+ virtual void setFireInterval(double interval) { m_nextFireTime = interval + currentTime(); }
+ virtual void stop() { m_nextFireTime = 0; }
+
+ bool isActive() { return m_sharedTimerFunction && m_nextFireTime; }
+ double fireTime() { return m_nextFireTime; }
+ void fire() { m_sharedTimerFunction(); }
+
+private:
+ void (*m_sharedTimerFunction)();
+ double m_nextFireTime;
+};
+
+WorkerRunLoop::WorkerRunLoop()
+ : m_sharedTimer(adoptPtr(new WorkerSharedTimer))
+ , m_context(0)
+ , m_nestedCount(0)
+{
+}
+
+WorkerRunLoop::~WorkerRunLoop()
+{
+ ASSERT(!m_nestedCount);
+}
+
+class RunLoopSetup {
+ WTF_MAKE_NONCOPYABLE(RunLoopSetup);
+public:
+ RunLoopSetup(WorkerRunLoop& runLoop, WorkerGlobalScope* context)
+ : m_runLoop(runLoop)
+ , m_context(context)
+ {
+ if (!m_runLoop.m_nestedCount)
+ PlatformThreadData::current().threadTimers().setSharedTimer(m_runLoop.m_sharedTimer.get());
+ m_runLoop.m_nestedCount++;
+ InspectorInstrumentation::willEnterNestedRunLoop(m_context);
+ }
+
+ ~RunLoopSetup()
+ {
+ m_runLoop.m_nestedCount--;
+ if (!m_runLoop.m_nestedCount)
+ PlatformThreadData::current().threadTimers().setSharedTimer(0);
+ InspectorInstrumentation::didLeaveNestedRunLoop(m_context);
+ }
+private:
+ WorkerRunLoop& m_runLoop;
+ WorkerGlobalScope* m_context;
+};
+
+void WorkerRunLoop::setWorkerGlobalScope(WorkerGlobalScope* context)
+{
+ ASSERT(!m_context);
+ ASSERT(context);
+ m_context = context;
+}
+
+void WorkerRunLoop::run()
+{
+ ASSERT(m_context);
+ RunLoopSetup setup(*this, m_context);
+ MessageQueueWaitResult result;
+ do {
+ ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
+ result = run(m_messageQueue, WaitForMessage);
+ } while (result != MessageQueueTerminated);
+ runCleanupTasks();
+}
+
+MessageQueueWaitResult WorkerRunLoop::runDebuggerTask(WaitMode waitMode)
+{
+ ASSERT(m_context);
+ RunLoopSetup setup(*this, m_context);
+ return run(m_debuggerMessageQueue, waitMode);
+}
+
+MessageQueueWaitResult WorkerRunLoop::run(MessageQueue<blink::WebThread::Task>& queue, WaitMode waitMode)
+{
+ ASSERT(m_context);
+ ASSERT(m_context->thread());
+ ASSERT(m_context->thread()->isCurrentThread());
+
+ bool isDebuggerQueue = (&queue == &m_debuggerMessageQueue);
+ bool nextTimeoutEventIsIdleWatchdog;
+ MessageQueueWaitResult result;
+ OwnPtr<blink::WebThread::Task> task;
+ do {
+ double absoluteTime = 0.0;
+ nextTimeoutEventIsIdleWatchdog = false;
+ if (waitMode == WaitForMessage) {
+ absoluteTime = !isDebuggerQueue && m_sharedTimer->isActive() ? m_sharedTimer->fireTime() : MessageQueue<blink::WebThread::Task>::infiniteTime();
+
+ // Do a script engine idle notification if the next event is distant enough.
+ const double kMinIdleTimespan = 0.3; // seconds
+ if (queue.isEmpty() && absoluteTime > currentTime() + kMinIdleTimespan) {
+ bool hasMoreWork = !m_context->idleNotification();
+ if (hasMoreWork) {
+ // Schedule a watchdog, so if there are no events within a particular time interval
+ // idle notifications won't stop firing.
+ const double kWatchdogInterval = 3; // seconds
+ double nextWatchdogTime = currentTime() + kWatchdogInterval;
+ if (absoluteTime > nextWatchdogTime) {
+ absoluteTime = nextWatchdogTime;
+ nextTimeoutEventIsIdleWatchdog = true;
+ }
+ }
+ }
+ }
+
+ {
+ ThreadState::SafePointScope safePointScope(ThreadState::NoHeapPointersOnStack);
+ task = queue.waitForMessageWithTimeout(result, absoluteTime);
+ }
+ } while (result == MessageQueueTimeout && nextTimeoutEventIsIdleWatchdog);
+
+ // If the context is closing, don't execute any further JavaScript tasks (per section 4.1.1 of the Web Workers spec).
+ // However, there may be implementation cleanup tasks in the queue, so keep running through it.
+
+ switch (result) {
+ case MessageQueueTerminated:
+ break;
+
+ case MessageQueueMessageReceived:
+ InspectorInstrumentation::willProcessTask(m_context);
+ task->run();
+ InspectorInstrumentation::didProcessTask(m_context);
+ break;
+
+ case MessageQueueTimeout:
+ ASSERT(!isDebuggerQueue || waitMode != WaitForMessage);
+ if (!m_context->isClosing())
+ m_sharedTimer->fire();
+ break;
+ }
+
+ return result;
+}
+
+void WorkerRunLoop::runCleanupTasks()
+{
+ ASSERT(m_context);
+ ASSERT(m_context->thread());
+ ASSERT(m_context->thread()->isCurrentThread());
+ ASSERT(m_messageQueue.killed());
+ ASSERT(m_debuggerMessageQueue.killed());
+
+ while (true) {
+ OwnPtr<blink::WebThread::Task> task = m_debuggerMessageQueue.tryGetMessageIgnoringKilled();
+ if (!task)
+ task = m_messageQueue.tryGetMessageIgnoringKilled();
+ if (!task)
+ return;
+ task->run();
+ }
+}
+
+void WorkerRunLoop::terminate()
+{
+ InspectorInstrumentation::didKillAllExecutionContextTasks(m_context);
+ m_messageQueue.kill();
+ m_debuggerMessageQueue.kill();
+}
+
+bool WorkerRunLoop::postTask(PassOwnPtr<ExecutionContextTask> task)
+{
+ return m_messageQueue.append(WorkerRunLoopTask::create(*this, task, true));
+}
+
+void WorkerRunLoop::postTaskAndTerminate(PassOwnPtr<ExecutionContextTask> task)
+{
+ InspectorInstrumentation::didKillAllExecutionContextTasks(m_context);
+ m_debuggerMessageQueue.kill();
+ m_messageQueue.appendAndKill(WorkerRunLoopTask::create(*this, task, false));
+}
+
+bool WorkerRunLoop::postDebuggerTask(PassOwnPtr<ExecutionContextTask> task)
+{
+ bool posted = m_debuggerMessageQueue.append(WorkerRunLoopTask::create(*this, task, false));
+ if (posted)
+ postTask(TickleDebuggerQueueTask::create(this));
+ return posted;
+}
+
+} // namespace blink
« no previous file with comments | « Source/core/workers/WorkerRunLoop.h ('k') | Source/core/workers/WorkerThread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698