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 20 matching lines...) Expand all Loading... |
31 #include "bindings/core/v8/ScriptSourceCode.h" | 31 #include "bindings/core/v8/ScriptSourceCode.h" |
32 #include "bindings/core/v8/V8GCController.h" | 32 #include "bindings/core/v8/V8GCController.h" |
33 #include "bindings/core/v8/V8Initializer.h" | 33 #include "bindings/core/v8/V8Initializer.h" |
34 #include "core/dom/Microtask.h" | 34 #include "core/dom/Microtask.h" |
35 #include "core/inspector/InspectorInstrumentation.h" | 35 #include "core/inspector/InspectorInstrumentation.h" |
36 #include "core/inspector/WorkerInspectorController.h" | 36 #include "core/inspector/WorkerInspectorController.h" |
37 #include "core/workers/DedicatedWorkerGlobalScope.h" | 37 #include "core/workers/DedicatedWorkerGlobalScope.h" |
38 #include "core/workers/WorkerClients.h" | 38 #include "core/workers/WorkerClients.h" |
39 #include "core/workers/WorkerReportingProxy.h" | 39 #include "core/workers/WorkerReportingProxy.h" |
40 #include "core/workers/WorkerThreadStartupData.h" | 40 #include "core/workers/WorkerThreadStartupData.h" |
| 41 #include "platform/PlatformThreadData.h" |
41 #include "platform/Task.h" | 42 #include "platform/Task.h" |
42 #include "platform/ThreadSafeFunctional.h" | 43 #include "platform/ThreadSafeFunctional.h" |
| 44 #include "platform/ThreadTimers.h" |
43 #include "platform/heap/SafePoint.h" | 45 #include "platform/heap/SafePoint.h" |
44 #include "platform/heap/ThreadState.h" | 46 #include "platform/heap/ThreadState.h" |
45 #include "platform/weborigin/KURL.h" | 47 #include "platform/weborigin/KURL.h" |
46 #include "public/platform/Platform.h" | 48 #include "public/platform/Platform.h" |
47 #include "public/platform/WebScheduler.h" | 49 #include "public/platform/WebScheduler.h" |
48 #include "public/platform/WebThread.h" | 50 #include "public/platform/WebThread.h" |
49 #include "public/platform/WebWaitableEvent.h" | 51 #include "public/platform/WebWaitableEvent.h" |
50 #include "wtf/Noncopyable.h" | 52 #include "wtf/Noncopyable.h" |
51 #include "wtf/WeakPtr.h" | 53 #include "wtf/WeakPtr.h" |
52 #include "wtf/text/WTFString.h" | 54 #include "wtf/text/WTFString.h" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ()); | 104 DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ()); |
103 return threads; | 105 return threads; |
104 } | 106 } |
105 | 107 |
106 unsigned WorkerThread::workerThreadCount() | 108 unsigned WorkerThread::workerThreadCount() |
107 { | 109 { |
108 MutexLocker lock(threadSetMutex()); | 110 MutexLocker lock(threadSetMutex()); |
109 return workerThreads().size(); | 111 return workerThreads().size(); |
110 } | 112 } |
111 | 113 |
| 114 class WorkerThreadCancelableTask final : public ExecutionContextTask { |
| 115 WTF_MAKE_NONCOPYABLE(WorkerThreadCancelableTask); WTF_MAKE_FAST_ALLOCATED(Wo
rkerThreadCancelableTask); |
| 116 public: |
| 117 static PassOwnPtr<WorkerThreadCancelableTask> create(PassOwnPtr<Closure> clo
sure) |
| 118 { |
| 119 return adoptPtr(new WorkerThreadCancelableTask(closure)); |
| 120 } |
| 121 |
| 122 virtual ~WorkerThreadCancelableTask() { } |
| 123 |
| 124 virtual void performTask(ExecutionContext*) override |
| 125 { |
| 126 if (!m_taskCanceled) |
| 127 (*m_closure)(); |
| 128 } |
| 129 |
| 130 WeakPtr<WorkerThreadCancelableTask> createWeakPtr() { return m_weakFactory.c
reateWeakPtr(); } |
| 131 void cancelTask() { m_taskCanceled = true; } |
| 132 |
| 133 private: |
| 134 explicit WorkerThreadCancelableTask(PassOwnPtr<Closure> closure) |
| 135 : m_closure(closure) |
| 136 , m_weakFactory(this) |
| 137 , m_taskCanceled(false) |
| 138 { } |
| 139 |
| 140 OwnPtr<Closure> m_closure; |
| 141 WeakPtrFactory<WorkerThreadCancelableTask> m_weakFactory; |
| 142 bool m_taskCanceled; |
| 143 }; |
| 144 |
| 145 class WorkerSharedTimer : public SharedTimer { |
| 146 public: |
| 147 explicit WorkerSharedTimer(WorkerThread* workerThread) |
| 148 : m_workerThread(workerThread) |
| 149 , m_running(false) |
| 150 { } |
| 151 |
| 152 typedef void (*SharedTimerFunction)(); |
| 153 virtual void setFiredFunction(SharedTimerFunction func) |
| 154 { |
| 155 m_sharedTimerFunction = func; |
| 156 } |
| 157 |
| 158 virtual void setFireInterval(double interval) |
| 159 { |
| 160 ASSERT(m_sharedTimerFunction); |
| 161 |
| 162 // See BlinkPlatformImpl::setSharedTimerFireInterval for explanation of |
| 163 // why ceil is used in the interval calculation. |
| 164 int64_t delay = static_cast<int64_t>(ceil(interval * 1000)); |
| 165 |
| 166 if (delay < 0) { |
| 167 delay = 0; |
| 168 } |
| 169 |
| 170 m_running = true; |
| 171 |
| 172 if (m_lastQueuedTask.get()) |
| 173 m_lastQueuedTask->cancelTask(); |
| 174 |
| 175 // Now queue the task as a cancellable one. |
| 176 OwnPtr<WorkerThreadCancelableTask> task = WorkerThreadCancelableTask::cr
eate(bind(&WorkerSharedTimer::OnTimeout, this)); |
| 177 m_lastQueuedTask = task->createWeakPtr(); |
| 178 m_workerThread->postDelayedTask(FROM_HERE, task.release(), delay); |
| 179 } |
| 180 |
| 181 virtual void stop() |
| 182 { |
| 183 m_running = false; |
| 184 m_lastQueuedTask = nullptr; |
| 185 } |
| 186 |
| 187 private: |
| 188 void OnTimeout() |
| 189 { |
| 190 ASSERT(m_workerThread->workerGlobalScope()); |
| 191 |
| 192 m_lastQueuedTask = nullptr; |
| 193 |
| 194 if (m_sharedTimerFunction && m_running && !m_workerThread->workerGlobalS
cope()->isClosing()) |
| 195 m_sharedTimerFunction(); |
| 196 } |
| 197 |
| 198 WorkerThread* m_workerThread; |
| 199 SharedTimerFunction m_sharedTimerFunction; |
| 200 bool m_running; |
| 201 |
| 202 // The task to run OnTimeout, if any. While OnTimeout resets |
| 203 // m_lastQueuedTask, this must be a weak pointer because the |
| 204 // worker runloop may delete the task as it is shutting down. |
| 205 WeakPtr<WorkerThreadCancelableTask> m_lastQueuedTask; |
| 206 }; |
| 207 |
112 class WorkerThreadTask : public WebThread::Task { | 208 class WorkerThreadTask : public WebThread::Task { |
113 WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED(WorkerThread
Task); | 209 WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED(WorkerThread
Task); |
114 public: | 210 public: |
115 static PassOwnPtr<WorkerThreadTask> create(WorkerThread& workerThread, PassO
wnPtr<ExecutionContextTask> task, bool isInstrumented) | 211 static PassOwnPtr<WorkerThreadTask> create(WorkerThread& workerThread, PassO
wnPtr<ExecutionContextTask> task, bool isInstrumented) |
116 { | 212 { |
117 return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented)
); | 213 return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented)
); |
118 } | 214 } |
119 | 215 |
120 virtual ~WorkerThreadTask() { } | 216 virtual ~WorkerThreadTask() { } |
121 | 217 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 return; | 313 return; |
218 } | 314 } |
219 | 315 |
220 m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this)); | 316 m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this)); |
221 backingThread().addTaskObserver(m_microtaskRunner.get()); | 317 backingThread().addTaskObserver(m_microtaskRunner.get()); |
222 backingThread().initialize(); | 318 backingThread().initialize(); |
223 | 319 |
224 m_isolate = initializeIsolate(); | 320 m_isolate = initializeIsolate(); |
225 m_workerGlobalScope = createWorkerGlobalScope(startupData); | 321 m_workerGlobalScope = createWorkerGlobalScope(startupData); |
226 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge
t() ? cachedMetaData->size() : 0); | 322 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge
t() ? cachedMetaData->size() : 0); |
| 323 |
| 324 PlatformThreadData::current().threadTimers().setSharedTimer(adoptPtr(new
WorkerSharedTimer(this))); |
227 } | 325 } |
228 m_webScheduler = backingThread().platformThread().scheduler(); | 326 m_webScheduler = backingThread().platformThread().scheduler(); |
229 | 327 |
230 // The corresponding call to stopRunLoop() is in ~WorkerScriptController(). | 328 // The corresponding call to stopRunLoop() is in ~WorkerScriptController(). |
231 didStartRunLoop(); | 329 didStartRunLoop(); |
232 | 330 |
233 // Notify proxy that a new WorkerGlobalScope has been created and started. | 331 // Notify proxy that a new WorkerGlobalScope has been created and started. |
234 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get()); | 332 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get()); |
235 | 333 |
236 WorkerScriptController* script = m_workerGlobalScope->script(); | 334 WorkerScriptController* script = m_workerGlobalScope->script(); |
(...skipping 14 matching lines...) Expand all Loading... |
251 | 349 |
252 void WorkerThread::shutdown() | 350 void WorkerThread::shutdown() |
253 { | 351 { |
254 ASSERT(isCurrentThread()); | 352 ASSERT(isCurrentThread()); |
255 { | 353 { |
256 MutexLocker lock(m_threadStateMutex); | 354 MutexLocker lock(m_threadStateMutex); |
257 ASSERT(!m_shutdown); | 355 ASSERT(!m_shutdown); |
258 m_shutdown = true; | 356 m_shutdown = true; |
259 } | 357 } |
260 | 358 |
| 359 PlatformThreadData::current().threadTimers().setSharedTimer(nullptr); |
261 workerGlobalScope()->dispose(); | 360 workerGlobalScope()->dispose(); |
262 willDestroyIsolate(); | 361 willDestroyIsolate(); |
263 | 362 |
264 // This should be called before we start the shutdown procedure. | 363 // This should be called before we start the shutdown procedure. |
265 workerReportingProxy().willDestroyWorkerGlobalScope(); | 364 workerReportingProxy().willDestroyWorkerGlobalScope(); |
266 | 365 |
267 // The below assignment will destroy the context, which will in turn notify
messaging proxy. | 366 // The below assignment will destroy the context, which will in turn notify
messaging proxy. |
268 // We cannot let any objects survive past thread exit, because no other thre
ad will run GC or otherwise destroy them. | 367 // We cannot let any objects survive past thread exit, because no other thre
ad will run GC or otherwise destroy them. |
269 // If Oilpan is enabled, we detach of the context/global scope, with the fin
al heap cleanup below sweeping it out. | 368 // If Oilpan is enabled, we detach of the context/global scope, with the fin
al heap cleanup below sweeping it out. |
270 #if !ENABLE(OILPAN) | 369 #if !ENABLE(OILPAN) |
271 ASSERT(m_workerGlobalScope->hasOneRef()); | 370 ASSERT(m_workerGlobalScope->hasOneRef()); |
272 #endif | 371 #endif |
273 m_workerGlobalScope->notifyContextDestroyed(); | 372 m_workerGlobalScope->notifyContextDestroyed(); |
274 m_workerGlobalScope = nullptr; | 373 m_workerGlobalScope = nullptr; |
275 | 374 |
276 backingThread().removeTaskObserver(m_microtaskRunner.get()); | 375 backingThread().removeTaskObserver(m_microtaskRunner.get()); |
277 backingThread().shutdown(); | 376 backingThread().shutdown(); |
278 destroyIsolate(); | 377 destroyIsolate(); |
279 | 378 |
280 m_microtaskRunner = nullptr; | 379 m_microtaskRunner = nullptr; |
281 | 380 |
282 // Notify the proxy that the WorkerGlobalScope has been disposed of. | 381 // Notify the proxy that the WorkerGlobalScope has been disposed of. |
283 // This can free this thread object, hence it must not be touched afterwards
. | 382 // This can free this thread object, hence it must not be touched afterwards
. |
284 workerReportingProxy().workerThreadTerminated(); | 383 workerReportingProxy().workerThreadTerminated(); |
285 | 384 |
286 m_terminationEvent->signal(); | 385 m_terminationEvent->signal(); |
| 386 |
| 387 // Clean up PlatformThreadData before WTF::WTFThreadData goes away! |
| 388 PlatformThreadData::current().destroy(); |
287 } | 389 } |
288 | 390 |
289 | 391 |
290 void WorkerThread::stop() | 392 void WorkerThread::stop() |
291 { | 393 { |
292 // Prevent the deadlock between GC and an attempt to stop a thread. | 394 // Prevent the deadlock between GC and an attempt to stop a thread. |
293 SafePointScope safePointScope(ThreadState::HeapPointersOnStack); | 395 SafePointScope safePointScope(ThreadState::HeapPointersOnStack); |
294 stopInternal(); | 396 stopInternal(); |
295 } | 397 } |
296 | 398 |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); | 580 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); |
479 } | 581 } |
480 | 582 |
481 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) | 583 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) |
482 { | 584 { |
483 MutexLocker locker(m_workerInspectorControllerMutex); | 585 MutexLocker locker(m_workerInspectorControllerMutex); |
484 m_workerInspectorController = workerInspectorController; | 586 m_workerInspectorController = workerInspectorController; |
485 } | 587 } |
486 | 588 |
487 } // namespace blink | 589 } // namespace blink |
OLD | NEW |