OLD | NEW |
---|---|
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 17 matching lines...) Expand all Loading... | |
28 | 28 |
29 #include "core/workers/WorkerThread.h" | 29 #include "core/workers/WorkerThread.h" |
30 | 30 |
31 #include "bindings/core/v8/ScriptSourceCode.h" | 31 #include "bindings/core/v8/ScriptSourceCode.h" |
32 #include "core/inspector/InspectorInstrumentation.h" | 32 #include "core/inspector/InspectorInstrumentation.h" |
33 #include "core/workers/DedicatedWorkerGlobalScope.h" | 33 #include "core/workers/DedicatedWorkerGlobalScope.h" |
34 #include "core/workers/WorkerClients.h" | 34 #include "core/workers/WorkerClients.h" |
35 #include "core/workers/WorkerReportingProxy.h" | 35 #include "core/workers/WorkerReportingProxy.h" |
36 #include "core/workers/WorkerThreadStartupData.h" | 36 #include "core/workers/WorkerThreadStartupData.h" |
37 #include "platform/PlatformThreadData.h" | 37 #include "platform/PlatformThreadData.h" |
38 #include "platform/Task.h" | |
39 #include "platform/ThreadTimers.h" | |
38 #include "platform/heap/ThreadState.h" | 40 #include "platform/heap/ThreadState.h" |
39 #include "platform/weborigin/KURL.h" | 41 #include "platform/weborigin/KURL.h" |
40 #include "public/platform/Platform.h" | 42 #include "public/platform/Platform.h" |
43 #include "public/platform/WebThread.h" | |
41 #include "public/platform/WebWaitableEvent.h" | 44 #include "public/platform/WebWaitableEvent.h" |
42 #include "public/platform/WebWorkerRunLoop.h" | 45 #include "public/platform/WebWorkerRunLoop.h" |
43 #include "wtf/Noncopyable.h" | 46 #include "wtf/Noncopyable.h" |
44 #include "wtf/text/WTFString.h" | 47 #include "wtf/text/WTFString.h" |
45 | 48 |
46 #include <utility> | 49 #include <utility> |
47 | 50 |
48 namespace blink { | 51 namespace blink { |
49 | 52 |
53 namespace { | |
54 const int64 kShortIdleHandlerDelayMs = 1000; | |
55 const int64 kLongIdleHandlerDelayMs = 10*1000; | |
56 } | |
57 | |
50 static Mutex& threadSetMutex() | 58 static Mutex& threadSetMutex() |
51 { | 59 { |
52 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); | 60 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); |
53 return mutex; | 61 return mutex; |
54 } | 62 } |
55 | 63 |
56 static HashSet<WorkerThread*>& workerThreads() | 64 static HashSet<WorkerThread*>& workerThreads() |
57 { | 65 { |
58 DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ()); | 66 DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ()); |
59 return threads; | 67 return threads; |
60 } | 68 } |
61 | 69 |
62 unsigned WorkerThread::workerThreadCount() | 70 unsigned WorkerThread::workerThreadCount() |
63 { | 71 { |
64 MutexLocker lock(threadSetMutex()); | 72 MutexLocker lock(threadSetMutex()); |
65 return workerThreads().size(); | 73 return workerThreads().size(); |
66 } | 74 } |
67 | 75 |
76 class WorkerSharedTimer : public SharedTimer { | |
77 public: | |
78 explicit WorkerSharedTimer(blink::WebThread* webThread) | |
79 : m_thread(webThread) | |
80 , m_nextFireTime(0.0) | |
81 { } | |
82 | |
83 virtual void setFiredFunction(blink::WebThread::SharedTimerFunction func) | |
84 { | |
85 m_thread->setSharedTimerFiredFunction(func); | |
86 if (!func) | |
87 m_nextFireTime = 0.0; | |
88 } | |
89 virtual void setFireInterval(double interval) | |
90 { | |
91 m_thread->setSharedTimerFireInterval(interval); | |
92 m_nextFireTime = interval + currentTime(); | |
93 } | |
94 virtual void stop() | |
95 { | |
96 m_thread->stopSharedTimer(); | |
97 } | |
98 | |
99 double nextFireTime() { return m_nextFireTime; } | |
100 | |
101 private: | |
102 blink::WebThread* m_thread; | |
103 double m_nextFireTime; | |
104 }; | |
105 | |
106 class WorkerThreadTask : public blink::WebThread::Task { | |
107 WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED; | |
108 public: | |
109 static PassOwnPtr<WorkerThreadTask> create(const WorkerThread& workerThread, PassOwnPtr<ExecutionContextTask> task, bool isInstrumented) | |
110 { | |
111 return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented) ); | |
112 } | |
113 | |
114 virtual ~WorkerThreadTask() { } | |
115 | |
116 virtual void run() OVERRIDE | |
117 { | |
118 WorkerGlobalScope* workerGlobalScope = m_workerThread.workerGlobalScope( ); | |
119 if (m_isInstrumented) | |
120 InspectorInstrumentation::willPerformExecutionContextTask(workerGlob alScope, m_task.get()); | |
121 if ((!workerGlobalScope->isClosing() && !m_workerThread.terminated()) || m_task->isCleanupTask()) | |
122 m_task->performTask(workerGlobalScope); | |
123 if (m_isInstrumented) | |
124 InspectorInstrumentation::didPerformExecutionContextTask(workerGloba lScope); | |
125 } | |
126 | |
127 private: | |
128 WorkerThreadTask(const WorkerThread& workerThread, PassOwnPtr<ExecutionConte xtTask> task, bool isInstrumented) | |
129 : m_workerThread(workerThread) | |
130 , m_task(task) | |
131 , m_isInstrumented(isInstrumented) | |
132 { | |
133 if (m_isInstrumented) | |
134 m_isInstrumented = !m_task->taskNameForInstrumentation().isEmpty(); | |
135 if (m_isInstrumented) | |
136 InspectorInstrumentation::didPostExecutionContextTask(m_workerThread .workerGlobalScope(), m_task.get()); | |
137 } | |
138 | |
139 const WorkerThread& m_workerThread; | |
140 OwnPtr<ExecutionContextTask> m_task; | |
141 bool m_isInstrumented; | |
142 }; | |
143 | |
144 class RunDebuggerQueueTask FINAL : public ExecutionContextTask { | |
145 public: | |
146 static PassOwnPtr<RunDebuggerQueueTask> create(WorkerThread* thread) | |
147 { | |
148 return adoptPtr(new RunDebuggerQueueTask(thread)); | |
149 } | |
150 virtual void performTask(ExecutionContext* context) OVERRIDE | |
151 { | |
152 ASSERT(context->isWorkerGlobalScope()); | |
153 m_thread->runDebuggerTask(WorkerThread::DontWaitForMessage); | |
154 } | |
155 | |
156 private: | |
157 explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { } | |
158 | |
159 WorkerThread* m_thread; | |
160 }; | |
161 | |
68 WorkerThread::WorkerThread(WorkerLoaderProxy& workerLoaderProxy, WorkerReporting Proxy& workerReportingProxy, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData> sta rtupData) | 162 WorkerThread::WorkerThread(WorkerLoaderProxy& workerLoaderProxy, WorkerReporting Proxy& workerReportingProxy, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData> sta rtupData) |
69 : m_threadID(0) | 163 : m_terminated(false) |
70 , m_workerLoaderProxy(workerLoaderProxy) | 164 , m_workerLoaderProxy(workerLoaderProxy) |
71 , m_workerReportingProxy(workerReportingProxy) | 165 , m_workerReportingProxy(workerReportingProxy) |
72 , m_startupData(startupData) | 166 , m_startupData(startupData) |
73 , m_shutdownEvent(adoptPtr(blink::Platform::current()->createWaitableEvent() )) | 167 , m_shutdownEvent(adoptPtr(blink::Platform::current()->createWaitableEvent() )) |
74 { | 168 { |
75 MutexLocker lock(threadSetMutex()); | 169 MutexLocker lock(threadSetMutex()); |
76 workerThreads().add(this); | 170 workerThreads().add(this); |
77 } | 171 } |
78 | 172 |
79 WorkerThread::~WorkerThread() | 173 WorkerThread::~WorkerThread() |
80 { | 174 { |
81 MutexLocker lock(threadSetMutex()); | 175 MutexLocker lock(threadSetMutex()); |
82 ASSERT(workerThreads().contains(this)); | 176 ASSERT(workerThreads().contains(this)); |
83 workerThreads().remove(this); | 177 workerThreads().remove(this); |
84 } | 178 } |
85 | 179 |
86 bool WorkerThread::start() | 180 void WorkerThread::start() |
87 { | 181 { |
88 // Mutex protection is necessary to ensure that m_threadID is initialized wh en the thread starts. | 182 if (m_thread) |
89 MutexLocker lock(m_threadCreationMutex); | 183 return; |
90 | 184 |
91 if (m_threadID) | 185 m_thread = adoptPtr(blink::Platform::current()->createThread("WebCore: Worke r")); |
92 return true; | 186 m_sharedTimer = adoptPtr(new WorkerSharedTimer(m_thread.get())); |
93 | 187 m_thread->postTask(new Task(WTF::bind(&WorkerThread::initialize, this))); |
94 m_threadID = createThread(WorkerThread::workerThreadStart, this, "WebCore: W orker"); | |
95 | |
96 return m_threadID; | |
97 } | 188 } |
98 | 189 |
99 void WorkerThread::workerThreadStart(void* thread) | 190 void WorkerThread::initialize() |
100 { | |
101 static_cast<WorkerThread*>(thread)->workerThread(); | |
102 } | |
103 | |
104 void WorkerThread::workerThread() | |
105 { | 191 { |
106 KURL scriptURL = m_startupData->m_scriptURL; | 192 KURL scriptURL = m_startupData->m_scriptURL; |
107 String sourceCode = m_startupData->m_sourceCode; | 193 String sourceCode = m_startupData->m_sourceCode; |
108 WorkerThreadStartMode startMode = m_startupData->m_startMode; | 194 WorkerThreadStartMode startMode = m_startupData->m_startMode; |
109 | 195 |
110 { | 196 { |
111 MutexLocker lock(m_threadCreationMutex); | 197 MutexLocker lock(m_threadCreationMutex); |
198 | |
112 ThreadState::attach(); | 199 ThreadState::attach(); |
113 m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release()); | 200 m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release()); |
114 m_runLoop.setWorkerGlobalScope(workerGlobalScope()); | |
115 | 201 |
116 if (m_runLoop.terminated()) { | 202 PlatformThreadData::current().threadTimers().setSharedTimer(m_sharedTime r.get()); |
203 | |
204 if (m_terminated) { | |
117 // The worker was terminated before the thread had a chance to run. Since the context didn't exist yet, | 205 // The worker was terminated before the thread had a chance to run. Since the context didn't exist yet, |
118 // forbidExecution() couldn't be called from stop(). | 206 // forbidExecution() couldn't be called from stop(). |
119 m_workerGlobalScope->script()->forbidExecution(); | 207 m_workerGlobalScope->script()->forbidExecution(); |
120 } | 208 } |
121 } | 209 } |
122 // The corresponding call to didStopWorkerRunLoop is in | 210 |
211 // The corresponding call to didStopWorkerThread is in | |
123 // ~WorkerScriptController. | 212 // ~WorkerScriptController. |
124 blink::Platform::current()->didStartWorkerRunLoop(blink::WebWorkerRunLoop(&m _runLoop)); | 213 blink::Platform::current()->didStartWorkerThread(m_thread.get()); |
125 | 214 |
126 // Notify proxy that a new WorkerGlobalScope has been created and started. | 215 // Notify proxy that a new WorkerGlobalScope has been created and started. |
127 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get()); | 216 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get()); |
128 | 217 |
129 WorkerScriptController* script = m_workerGlobalScope->script(); | 218 WorkerScriptController* script = m_workerGlobalScope->script(); |
130 if (!script->isExecutionForbidden()) | 219 if (!script->isExecutionForbidden()) |
131 script->initializeContextIfNeeded(); | 220 script->initializeContextIfNeeded(); |
132 InspectorInstrumentation::willEvaluateWorkerScript(workerGlobalScope(), star tMode); | 221 InspectorInstrumentation::willEvaluateWorkerScript(workerGlobalScope(), star tMode); |
133 script->evaluate(ScriptSourceCode(sourceCode, scriptURL)); | 222 script->evaluate(ScriptSourceCode(sourceCode, scriptURL)); |
134 | 223 |
135 runEventLoop(); | 224 postInitialize(); |
225 | |
226 m_weakFactory = adoptPtr(new WeakPtrFactory<WorkerThread>(this)); | |
227 m_thread->postDelayedTask(new Task(WTF::bind(&WorkerThread::idleHandler, m_w eakFactory->createWeakPtr())), kShortIdleHandlerDelayMs); | |
228 } | |
229 | |
230 void WorkerThread::cleanup() | |
231 { | |
232 m_weakFactory.release(); | |
136 | 233 |
137 // This should be called before we start the shutdown procedure. | 234 // This should be called before we start the shutdown procedure. |
138 workerReportingProxy().willDestroyWorkerGlobalScope(); | 235 workerReportingProxy().willDestroyWorkerGlobalScope(); |
139 | 236 |
140 ThreadIdentifier threadID = m_threadID; | |
141 | |
142 // The below assignment will destroy the context, which will in turn notify messaging proxy. | 237 // The below assignment will destroy the context, which will in turn notify messaging proxy. |
143 // We cannot let any objects survive past thread exit, because no other thre ad will run GC or otherwise destroy them. | 238 // We cannot let any objects survive past thread exit, because no other thre ad will run GC or otherwise destroy them. |
144 // If Oilpan is enabled, we detach of the context/global scope, with the fin al heap cleanup below sweeping it out. | 239 // If Oilpan is enabled, we detach of the context/global scope, with the fin al heap cleanup below sweeping it out. |
145 #if !ENABLE(OILPAN) | 240 #if !ENABLE(OILPAN) |
146 ASSERT(m_workerGlobalScope->hasOneRef()); | 241 ASSERT(m_workerGlobalScope->hasOneRef()); |
147 #endif | 242 #endif |
148 m_workerGlobalScope->dispose(); | 243 m_workerGlobalScope->dispose(); |
149 m_workerGlobalScope = nullptr; | 244 m_workerGlobalScope = nullptr; |
150 | 245 |
151 // Detach the ThreadState, cleaning out the thread's heap by | 246 // Detach the ThreadState, cleaning out the thread's heap by |
152 // performing a final GC. The cleanup operation will at the end | 247 // performing a final GC. The cleanup operation will at the end |
153 // assert that the heap is empty. If the heap does not become | 248 // assert that the heap is empty. If the heap does not become |
154 // empty, there are still pointers into the heap and those | 249 // empty, there are still pointers into the heap and those |
155 // pointers will be dangling after thread termination because we | 250 // pointers will be dangling after thread termination because we |
156 // are destroying the heap. It is important to detach while the | 251 // are destroying the heap. It is important to detach while the |
157 // thread is still valid. In particular, finalizers for objects in | 252 // thread is still valid. In particular, finalizers for objects in |
158 // the heap for this thread will need to access thread local data. | 253 // the heap for this thread will need to access thread local data. |
159 ThreadState::detach(); | 254 ThreadState::detach(); |
160 | 255 |
161 // Notify the proxy that the WorkerGlobalScope has been disposed of. | 256 // Notify the proxy that the WorkerGlobalScope has been disposed of. |
162 // This can free this thread object, hence it must not be touched afterwards . | 257 // This can free this thread object, hence it must not be touched afterwards . |
163 workerReportingProxy().workerGlobalScopeDestroyed(); | 258 workerReportingProxy().workerGlobalScopeDestroyed(); |
164 | 259 |
165 // Clean up PlatformThreadData before WTF::WTFThreadData goes away! | 260 // Clean up PlatformThreadData before WTF::WTFThreadData goes away! |
166 PlatformThreadData::current().destroy(); | 261 PlatformThreadData::current().destroy(); |
167 | 262 |
168 // The thread object may be already destroyed from notification now, don't t ry to access "this". | 263 // Set the timer function to null, which will cause the shared timer in |
169 detachThread(threadID); | 264 // WebThread to be deleted. It is important to do it here, since it |
170 } | 265 // should be deleted on the same thread that it executes on. |
171 | 266 m_sharedTimer->setFiredFunction(0); |
172 void WorkerThread::runEventLoop() | |
173 { | |
174 // Does not return until terminated. | |
175 m_runLoop.run(); | |
176 } | 267 } |
177 | 268 |
178 class WorkerThreadShutdownFinishTask : public ExecutionContextTask { | 269 class WorkerThreadShutdownFinishTask : public ExecutionContextTask { |
179 public: | 270 public: |
180 static PassOwnPtr<WorkerThreadShutdownFinishTask> create() | 271 static PassOwnPtr<WorkerThreadShutdownFinishTask> create() |
181 { | 272 { |
182 return adoptPtr(new WorkerThreadShutdownFinishTask()); | 273 return adoptPtr(new WorkerThreadShutdownFinishTask()); |
183 } | 274 } |
184 | 275 |
185 virtual void performTask(ExecutionContext *context) | 276 virtual void performTask(ExecutionContext *context) |
186 { | 277 { |
187 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); | 278 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); |
188 workerGlobalScope->clearInspector(); | 279 workerGlobalScope->clearInspector(); |
189 // It's not safe to call clearScript until all the cleanup tasks posted by functions initiated by WorkerThreadShutdownStartTask have completed. | 280 // It's not safe to call clearScript until all the cleanup tasks posted by functions initiated by WorkerThreadShutdownStartTask have completed. |
190 workerGlobalScope->clearScript(); | 281 workerGlobalScope->clearScript(); |
282 workerGlobalScope->thread()->webThread()->postTask(new Task(WTF::bind(&W orkerThread::cleanup, workerGlobalScope->thread()))); | |
191 } | 283 } |
192 | 284 |
193 virtual bool isCleanupTask() const { return true; } | 285 virtual bool isCleanupTask() const { return true; } |
194 }; | 286 }; |
195 | 287 |
196 class WorkerThreadShutdownStartTask : public ExecutionContextTask { | 288 class WorkerThreadShutdownStartTask : public ExecutionContextTask { |
197 public: | 289 public: |
198 static PassOwnPtr<WorkerThreadShutdownStartTask> create() | 290 static PassOwnPtr<WorkerThreadShutdownStartTask> create() |
199 { | 291 { |
200 return adoptPtr(new WorkerThreadShutdownStartTask()); | 292 return adoptPtr(new WorkerThreadShutdownStartTask()); |
201 } | 293 } |
202 | 294 |
203 virtual void performTask(ExecutionContext *context) | 295 virtual void performTask(ExecutionContext *context) |
204 { | 296 { |
205 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); | 297 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); |
206 workerGlobalScope->stopFetch(); | 298 workerGlobalScope->stopFetch(); |
207 workerGlobalScope->stopActiveDOMObjects(); | 299 workerGlobalScope->stopActiveDOMObjects(); |
300 workerGlobalScope->thread()->webThread()->stopSharedTimer(); | |
208 | 301 |
209 // Event listeners would keep DOMWrapperWorld objects alive for too long . Also, they have references to JS objects, | 302 // Event listeners would keep DOMWrapperWorld objects alive for too long . Also, they have references to JS objects, |
210 // which become dangling once Heap is destroyed. | 303 // which become dangling once Heap is destroyed. |
211 workerGlobalScope->removeAllEventListeners(); | 304 workerGlobalScope->removeAllEventListeners(); |
212 | 305 |
213 // Stick a shutdown command at the end of the queue, so that we deal | 306 // Stick a shutdown command at the end of the queue, so that we deal |
214 // with all the cleanup tasks the databases post first. | 307 // with all the cleanup tasks the databases post first. |
215 workerGlobalScope->postTask(WorkerThreadShutdownFinishTask::create()); | 308 workerGlobalScope->postTask(WorkerThreadShutdownFinishTask::create()); |
216 } | 309 } |
217 | 310 |
218 virtual bool isCleanupTask() const { return true; } | 311 virtual bool isCleanupTask() const { return true; } |
219 }; | 312 }; |
220 | 313 |
221 void WorkerThread::stop() | 314 void WorkerThread::stop() |
222 { | 315 { |
223 // Prevent the deadlock between GC and an attempt to stop a thread. | 316 // Prevent the deadlock between GC and an attempt to stop a thread. |
224 ThreadState::SafePointScope safePointScope(ThreadState::HeapPointersOnStack) ; | 317 ThreadState::SafePointScope safePointScope(ThreadState::HeapPointersOnStack) ; |
225 | 318 |
226 // Mutex protection is necessary because stop() can be called before the con text is fully created. | 319 // Protect against this method and initialize() racing each other. |
227 MutexLocker lock(m_threadCreationMutex); | 320 MutexLocker lock(m_threadCreationMutex); |
228 | 321 |
322 // If stop has already been called, just return. | |
323 if (m_terminated) | |
324 return; | |
325 | |
229 // Signal the thread to notify that the thread's stopping. | 326 // Signal the thread to notify that the thread's stopping. |
230 if (m_shutdownEvent) | 327 if (m_shutdownEvent) |
231 m_shutdownEvent->signal(); | 328 m_shutdownEvent->signal(); |
232 | 329 |
233 // Ensure that tasks are being handled by thread event loop. If script execu tion weren't forbidden, a while(1) loop in JS could keep the thread alive foreve r. | 330 // Ensure that tasks are being handled by thread event loop. If script execu tion weren't forbidden, a while(1) loop in JS could keep the thread alive foreve r. |
234 if (m_workerGlobalScope) { | 331 if (m_workerGlobalScope) { |
235 m_workerGlobalScope->script()->scheduleExecutionTermination(); | 332 m_workerGlobalScope->script()->scheduleExecutionTermination(); |
236 m_workerGlobalScope->wasRequestedToTerminate(); | 333 m_workerGlobalScope->wasRequestedToTerminate(); |
237 m_runLoop.postTaskAndTerminate(WorkerThreadShutdownStartTask::create()); | 334 InspectorInstrumentation::didKillAllExecutionContextTasks(m_workerGlobal Scope.get()); |
aandrey
2014/07/24 16:07:53
is it safe to access m_workerGlobalScope here?
if
nasko
2014/07/25 06:30:14
It is safe. It is used further in the WorkerThread
yurys
2014/07/25 06:41:56
It is unsafe to access m_workerGlobalScope here as
| |
335 postTask(WorkerThreadShutdownStartTask::create()); | |
336 m_terminated = true; | |
238 return; | 337 return; |
239 } | 338 } |
240 m_runLoop.terminate(); | |
241 } | 339 } |
242 | 340 |
243 bool WorkerThread::isCurrentThread() const | 341 bool WorkerThread::isCurrentThread() const |
244 { | 342 { |
245 return m_threadID == currentThread(); | 343 return m_thread && m_thread->isCurrentThread(); |
344 } | |
345 | |
346 void WorkerThread::idleHandler() | |
347 { | |
348 if (m_terminated) | |
349 return; | |
350 | |
351 int64 delay = kLongIdleHandlerDelayMs; | |
352 | |
353 // Do a script engine idle notification if the next event is distant enough. | |
354 const double kMinIdleTimespan = 0.3; | |
355 if (!m_sharedTimer->nextFireTime() || m_sharedTimer->nextFireTime() > curren tTime() + kMinIdleTimespan) { | |
356 bool hasMoreWork = !m_workerGlobalScope->idleNotification(); | |
357 if (hasMoreWork) | |
358 delay = kShortIdleHandlerDelayMs; | |
359 } | |
360 | |
361 m_thread->postDelayedTask(new Task(WTF::bind(&WorkerThread::idleHandler, m_w eakFactory->createWeakPtr())), delay); | |
246 } | 362 } |
247 | 363 |
248 void WorkerThread::postTask(PassOwnPtr<ExecutionContextTask> task) | 364 void WorkerThread::postTask(PassOwnPtr<ExecutionContextTask> task) |
249 { | 365 { |
250 m_runLoop.postTask(task); | 366 m_thread->postTask(WorkerThreadTask::create(*this, task, true).leakPtr()); |
251 } | 367 } |
252 | 368 |
253 void WorkerThread::postDebuggerTask(PassOwnPtr<ExecutionContextTask> task) | 369 void WorkerThread::postDebuggerTask(PassOwnPtr<ExecutionContextTask> task) |
254 { | 370 { |
255 m_runLoop.postDebuggerTask(task); | 371 m_debuggerMessageQueue.append(WorkerThreadTask::create(*this, task, false)); |
372 postTask(RunDebuggerQueueTask::create(this)); | |
256 } | 373 } |
257 | 374 |
258 MessageQueueWaitResult WorkerThread::runDebuggerTask(WorkerRunLoop::WaitMode wai tMode) | 375 MessageQueueWaitResult WorkerThread::runDebuggerTask(WaitMode waitMode) |
259 { | 376 { |
260 return m_runLoop.runDebuggerTask(waitMode); | 377 ASSERT(isCurrentThread()); |
378 MessageQueueWaitResult result; | |
379 double absoluteTime = MessageQueue<blink::WebThread::Task>::infiniteTime(); | |
380 OwnPtr<blink::WebThread::Task> task; | |
381 { | |
382 if (waitMode == DontWaitForMessage) | |
383 absoluteTime = 0.0; | |
384 ThreadState::SafePointScope safePointScope(ThreadState::NoHeapPointersOn Stack); | |
385 task = m_debuggerMessageQueue.waitForMessageWithTimeout(result, absolute Time); | |
386 } | |
387 | |
388 if (result == MessageQueueMessageReceived) { | |
389 InspectorInstrumentation::willProcessTask(workerGlobalScope()); | |
390 task->run(); | |
391 InspectorInstrumentation::didProcessTask(workerGlobalScope()); | |
392 } | |
393 | |
394 return result; | |
395 } | |
396 | |
397 void WorkerThread::willEnterNestedLoop() | |
398 { | |
399 InspectorInstrumentation::willEnterNestedRunLoop(m_workerGlobalScope.get()); | |
400 } | |
401 | |
402 void WorkerThread::didLeaveNestedLoop() | |
403 { | |
404 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); | |
261 } | 405 } |
262 | 406 |
263 } // namespace blink | 407 } // namespace blink |
OLD | NEW |