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

Side by Side Diff: Source/core/workers/WorkerRunLoop.cpp

Issue 423303004: Change WokerThread to use a blink::WebThread (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Remove changes made to WebThread. Created 6 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « Source/core/workers/WorkerRunLoop.h ('k') | Source/core/workers/WorkerThread.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32 #include "core/workers/WorkerRunLoop.h"
33
34 #include "core/inspector/InspectorInstrumentation.h"
35 #include "core/workers/WorkerGlobalScope.h"
36 #include "core/workers/WorkerThread.h"
37 #include "platform/PlatformThreadData.h"
38 #include "platform/SharedTimer.h"
39 #include "platform/ThreadTimers.h"
40 #include "platform/heap/ThreadState.h"
41 #include "wtf/CurrentTime.h"
42
43 namespace blink {
44
45 class WorkerRunLoopTask : public blink::WebThread::Task {
46 WTF_MAKE_NONCOPYABLE(WorkerRunLoopTask); WTF_MAKE_FAST_ALLOCATED;
47 public:
48 static PassOwnPtr<WorkerRunLoopTask> create(const WorkerRunLoop& runLoop, Pa ssOwnPtr<ExecutionContextTask> task, bool isInstrumented)
49 {
50 return adoptPtr(new WorkerRunLoopTask(runLoop, task, isInstrumented));
51 }
52
53 virtual ~WorkerRunLoopTask() { }
54
55 virtual void run() OVERRIDE
56 {
57 WorkerGlobalScope* workerGlobalScope = m_runLoop.context();
58 if (m_isInstrumented)
59 InspectorInstrumentation::willPerformExecutionContextTask(workerGlob alScope, m_task.get());
60 if ((!workerGlobalScope->isClosing() && !m_runLoop.terminated()) || m_ta sk->isCleanupTask())
61 m_task->performTask(workerGlobalScope);
62 if (m_isInstrumented)
63 InspectorInstrumentation::didPerformExecutionContextTask(workerGloba lScope);
64 }
65
66 private:
67 WorkerRunLoopTask(const WorkerRunLoop& runLoop, PassOwnPtr<ExecutionContextT ask> task, bool isInstrumented)
68 : m_runLoop(runLoop)
69 , m_task(task)
70 , m_isInstrumented(isInstrumented)
71 {
72 if (m_isInstrumented)
73 m_isInstrumented = !m_task->taskNameForInstrumentation().isEmpty();
74 if (m_isInstrumented)
75 InspectorInstrumentation::didPostExecutionContextTask(m_runLoop.cont ext(), m_task.get());
76 }
77
78 const WorkerRunLoop& m_runLoop;
79 OwnPtr<ExecutionContextTask> m_task;
80 bool m_isInstrumented;
81 };
82
83 class TickleDebuggerQueueTask FINAL : public ExecutionContextTask {
84 public:
85 static PassOwnPtr<TickleDebuggerQueueTask> create(WorkerRunLoop* loop)
86 {
87 return adoptPtr(new TickleDebuggerQueueTask(loop));
88 }
89 virtual void performTask(ExecutionContext* context) OVERRIDE
90 {
91 ASSERT(context->isWorkerGlobalScope());
92 m_loop->runDebuggerTask(WorkerRunLoop::DontWaitForMessage);
93 }
94
95 private:
96 explicit TickleDebuggerQueueTask(WorkerRunLoop* loop) : m_loop(loop) { }
97
98 WorkerRunLoop* m_loop;
99 };
100
101 class WorkerSharedTimer : public SharedTimer {
102 public:
103 WorkerSharedTimer()
104 : m_sharedTimerFunction(0)
105 , m_nextFireTime(0)
106 {
107 }
108
109 // SharedTimer interface.
110 virtual void setFiredFunction(void (*function)()) { m_sharedTimerFunction = function; }
111 virtual void setFireInterval(double interval) { m_nextFireTime = interval + currentTime(); }
112 virtual void stop() { m_nextFireTime = 0; }
113
114 bool isActive() { return m_sharedTimerFunction && m_nextFireTime; }
115 double fireTime() { return m_nextFireTime; }
116 void fire() { m_sharedTimerFunction(); }
117
118 private:
119 void (*m_sharedTimerFunction)();
120 double m_nextFireTime;
121 };
122
123 WorkerRunLoop::WorkerRunLoop()
124 : m_sharedTimer(adoptPtr(new WorkerSharedTimer))
125 , m_context(0)
126 , m_nestedCount(0)
127 {
128 }
129
130 WorkerRunLoop::~WorkerRunLoop()
131 {
132 ASSERT(!m_nestedCount);
133 }
134
135 class RunLoopSetup {
136 WTF_MAKE_NONCOPYABLE(RunLoopSetup);
137 public:
138 RunLoopSetup(WorkerRunLoop& runLoop, WorkerGlobalScope* context)
139 : m_runLoop(runLoop)
140 , m_context(context)
141 {
142 if (!m_runLoop.m_nestedCount)
143 PlatformThreadData::current().threadTimers().setSharedTimer(m_runLoo p.m_sharedTimer.get());
144 m_runLoop.m_nestedCount++;
145 InspectorInstrumentation::willEnterNestedRunLoop(m_context);
146 }
147
148 ~RunLoopSetup()
149 {
150 m_runLoop.m_nestedCount--;
151 if (!m_runLoop.m_nestedCount)
152 PlatformThreadData::current().threadTimers().setSharedTimer(0);
153 InspectorInstrumentation::didLeaveNestedRunLoop(m_context);
154 }
155 private:
156 WorkerRunLoop& m_runLoop;
157 WorkerGlobalScope* m_context;
158 };
159
160 void WorkerRunLoop::setWorkerGlobalScope(WorkerGlobalScope* context)
161 {
162 ASSERT(!m_context);
163 ASSERT(context);
164 m_context = context;
165 }
166
167 void WorkerRunLoop::run()
168 {
169 ASSERT(m_context);
170 RunLoopSetup setup(*this, m_context);
171 MessageQueueWaitResult result;
172 do {
173 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
174 result = run(m_messageQueue, WaitForMessage);
175 } while (result != MessageQueueTerminated);
176 runCleanupTasks();
177 }
178
179 MessageQueueWaitResult WorkerRunLoop::runDebuggerTask(WaitMode waitMode)
180 {
181 ASSERT(m_context);
182 RunLoopSetup setup(*this, m_context);
183 return run(m_debuggerMessageQueue, waitMode);
184 }
185
186 MessageQueueWaitResult WorkerRunLoop::run(MessageQueue<blink::WebThread::Task>& queue, WaitMode waitMode)
187 {
188 ASSERT(m_context);
189 ASSERT(m_context->thread());
190 ASSERT(m_context->thread()->isCurrentThread());
191
192 bool isDebuggerQueue = (&queue == &m_debuggerMessageQueue);
193 bool nextTimeoutEventIsIdleWatchdog;
194 MessageQueueWaitResult result;
195 OwnPtr<blink::WebThread::Task> task;
196 do {
197 double absoluteTime = 0.0;
198 nextTimeoutEventIsIdleWatchdog = false;
199 if (waitMode == WaitForMessage) {
200 absoluteTime = !isDebuggerQueue && m_sharedTimer->isActive() ? m_sha redTimer->fireTime() : MessageQueue<blink::WebThread::Task>::infiniteTime();
201
202 // Do a script engine idle notification if the next event is distant enough.
203 const double kMinIdleTimespan = 0.3; // seconds
204 if (queue.isEmpty() && absoluteTime > currentTime() + kMinIdleTimesp an) {
205 bool hasMoreWork = !m_context->idleNotification();
206 if (hasMoreWork) {
207 // Schedule a watchdog, so if there are no events within a p articular time interval
208 // idle notifications won't stop firing.
209 const double kWatchdogInterval = 3; // seconds
210 double nextWatchdogTime = currentTime() + kWatchdogInterval;
211 if (absoluteTime > nextWatchdogTime) {
212 absoluteTime = nextWatchdogTime;
213 nextTimeoutEventIsIdleWatchdog = true;
214 }
215 }
216 }
217 }
218
219 {
220 ThreadState::SafePointScope safePointScope(ThreadState::NoHeapPointe rsOnStack);
221 task = queue.waitForMessageWithTimeout(result, absoluteTime);
222 }
223 } while (result == MessageQueueTimeout && nextTimeoutEventIsIdleWatchdog);
224
225 // If the context is closing, don't execute any further JavaScript tasks (pe r section 4.1.1 of the Web Workers spec).
226 // However, there may be implementation cleanup tasks in the queue, so keep running through it.
227
228 switch (result) {
229 case MessageQueueTerminated:
230 break;
231
232 case MessageQueueMessageReceived:
233 InspectorInstrumentation::willProcessTask(m_context);
234 task->run();
235 InspectorInstrumentation::didProcessTask(m_context);
236 break;
237
238 case MessageQueueTimeout:
239 ASSERT(!isDebuggerQueue || waitMode != WaitForMessage);
240 if (!m_context->isClosing())
241 m_sharedTimer->fire();
242 break;
243 }
244
245 return result;
246 }
247
248 void WorkerRunLoop::runCleanupTasks()
249 {
250 ASSERT(m_context);
251 ASSERT(m_context->thread());
252 ASSERT(m_context->thread()->isCurrentThread());
253 ASSERT(m_messageQueue.killed());
254 ASSERT(m_debuggerMessageQueue.killed());
255
256 while (true) {
257 OwnPtr<blink::WebThread::Task> task = m_debuggerMessageQueue.tryGetMessa geIgnoringKilled();
258 if (!task)
259 task = m_messageQueue.tryGetMessageIgnoringKilled();
260 if (!task)
261 return;
262 task->run();
263 }
264 }
265
266 void WorkerRunLoop::terminate()
267 {
268 InspectorInstrumentation::didKillAllExecutionContextTasks(m_context);
269 m_messageQueue.kill();
270 m_debuggerMessageQueue.kill();
271 }
272
273 bool WorkerRunLoop::postTask(PassOwnPtr<ExecutionContextTask> task)
274 {
275 return m_messageQueue.append(WorkerRunLoopTask::create(*this, task, true));
276 }
277
278 void WorkerRunLoop::postTaskAndTerminate(PassOwnPtr<ExecutionContextTask> task)
279 {
280 InspectorInstrumentation::didKillAllExecutionContextTasks(m_context);
281 m_debuggerMessageQueue.kill();
282 m_messageQueue.appendAndKill(WorkerRunLoopTask::create(*this, task, false));
283 }
284
285 bool WorkerRunLoop::postDebuggerTask(PassOwnPtr<ExecutionContextTask> task)
286 {
287 bool posted = m_debuggerMessageQueue.append(WorkerRunLoopTask::create(*this, task, false));
288 if (posted)
289 postTask(TickleDebuggerQueueTask::create(this));
290 return posted;
291 }
292
293 } // namespace blink
OLDNEW
« 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