| 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" | |
| 42 #include "platform/Task.h" | 41 #include "platform/Task.h" |
| 43 #include "platform/ThreadSafeFunctional.h" | 42 #include "platform/ThreadSafeFunctional.h" |
| 44 #include "platform/ThreadTimers.h" | |
| 45 #include "platform/heap/SafePoint.h" | 43 #include "platform/heap/SafePoint.h" |
| 46 #include "platform/heap/ThreadState.h" | 44 #include "platform/heap/ThreadState.h" |
| 47 #include "platform/weborigin/KURL.h" | 45 #include "platform/weborigin/KURL.h" |
| 48 #include "public/platform/Platform.h" | 46 #include "public/platform/Platform.h" |
| 49 #include "public/platform/WebScheduler.h" | 47 #include "public/platform/WebScheduler.h" |
| 50 #include "public/platform/WebThread.h" | 48 #include "public/platform/WebThread.h" |
| 51 #include "public/platform/WebWaitableEvent.h" | 49 #include "public/platform/WebWaitableEvent.h" |
| 52 #include "wtf/Noncopyable.h" | 50 #include "wtf/Noncopyable.h" |
| 53 #include "wtf/WeakPtr.h" | 51 #include "wtf/WeakPtr.h" |
| 54 #include "wtf/text/WTFString.h" | 52 #include "wtf/text/WTFString.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ()); | 102 DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ()); |
| 105 return threads; | 103 return threads; |
| 106 } | 104 } |
| 107 | 105 |
| 108 unsigned WorkerThread::workerThreadCount() | 106 unsigned WorkerThread::workerThreadCount() |
| 109 { | 107 { |
| 110 MutexLocker lock(threadSetMutex()); | 108 MutexLocker lock(threadSetMutex()); |
| 111 return workerThreads().size(); | 109 return workerThreads().size(); |
| 112 } | 110 } |
| 113 | 111 |
| 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 | |
| 208 class WorkerThreadTask : public WebThread::Task { | 112 class WorkerThreadTask : public WebThread::Task { |
| 209 WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED(WorkerThread
Task); | 113 WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED(WorkerThread
Task); |
| 210 public: | 114 public: |
| 211 static PassOwnPtr<WorkerThreadTask> create(WorkerThread& workerThread, PassO
wnPtr<ExecutionContextTask> task, bool isInstrumented) | 115 static PassOwnPtr<WorkerThreadTask> create(WorkerThread& workerThread, PassO
wnPtr<ExecutionContextTask> task, bool isInstrumented) |
| 212 { | 116 { |
| 213 return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented)
); | 117 return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented)
); |
| 214 } | 118 } |
| 215 | 119 |
| 216 virtual ~WorkerThreadTask() { } | 120 virtual ~WorkerThreadTask() { } |
| 217 | 121 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 return; | 217 return; |
| 314 } | 218 } |
| 315 | 219 |
| 316 m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this)); | 220 m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this)); |
| 317 backingThread().addTaskObserver(m_microtaskRunner.get()); | 221 backingThread().addTaskObserver(m_microtaskRunner.get()); |
| 318 backingThread().initialize(); | 222 backingThread().initialize(); |
| 319 | 223 |
| 320 m_isolate = initializeIsolate(); | 224 m_isolate = initializeIsolate(); |
| 321 m_workerGlobalScope = createWorkerGlobalScope(startupData); | 225 m_workerGlobalScope = createWorkerGlobalScope(startupData); |
| 322 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge
t() ? cachedMetaData->size() : 0); | 226 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge
t() ? cachedMetaData->size() : 0); |
| 323 | |
| 324 PlatformThreadData::current().threadTimers().setSharedTimer(adoptPtr(new
WorkerSharedTimer(this))); | |
| 325 } | 227 } |
| 326 m_webScheduler = backingThread().platformThread().scheduler(); | 228 m_webScheduler = backingThread().platformThread().scheduler(); |
| 327 | 229 |
| 328 // The corresponding call to stopRunLoop() is in ~WorkerScriptController(). | 230 // The corresponding call to stopRunLoop() is in ~WorkerScriptController(). |
| 329 didStartRunLoop(); | 231 didStartRunLoop(); |
| 330 | 232 |
| 331 // Notify proxy that a new WorkerGlobalScope has been created and started. | 233 // Notify proxy that a new WorkerGlobalScope has been created and started. |
| 332 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get()); | 234 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get()); |
| 333 | 235 |
| 334 WorkerScriptController* script = m_workerGlobalScope->script(); | 236 WorkerScriptController* script = m_workerGlobalScope->script(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 349 | 251 |
| 350 void WorkerThread::shutdown() | 252 void WorkerThread::shutdown() |
| 351 { | 253 { |
| 352 ASSERT(isCurrentThread()); | 254 ASSERT(isCurrentThread()); |
| 353 { | 255 { |
| 354 MutexLocker lock(m_threadStateMutex); | 256 MutexLocker lock(m_threadStateMutex); |
| 355 ASSERT(!m_shutdown); | 257 ASSERT(!m_shutdown); |
| 356 m_shutdown = true; | 258 m_shutdown = true; |
| 357 } | 259 } |
| 358 | 260 |
| 359 PlatformThreadData::current().threadTimers().setSharedTimer(nullptr); | |
| 360 workerGlobalScope()->dispose(); | 261 workerGlobalScope()->dispose(); |
| 361 willDestroyIsolate(); | 262 willDestroyIsolate(); |
| 362 | 263 |
| 363 // This should be called before we start the shutdown procedure. | 264 // This should be called before we start the shutdown procedure. |
| 364 workerReportingProxy().willDestroyWorkerGlobalScope(); | 265 workerReportingProxy().willDestroyWorkerGlobalScope(); |
| 365 | 266 |
| 366 // The below assignment will destroy the context, which will in turn notify
messaging proxy. | 267 // The below assignment will destroy the context, which will in turn notify
messaging proxy. |
| 367 // We cannot let any objects survive past thread exit, because no other thre
ad will run GC or otherwise destroy them. | 268 // We cannot let any objects survive past thread exit, because no other thre
ad will run GC or otherwise destroy them. |
| 368 // If Oilpan is enabled, we detach of the context/global scope, with the fin
al heap cleanup below sweeping it out. | 269 // If Oilpan is enabled, we detach of the context/global scope, with the fin
al heap cleanup below sweeping it out. |
| 369 #if !ENABLE(OILPAN) | 270 #if !ENABLE(OILPAN) |
| 370 ASSERT(m_workerGlobalScope->hasOneRef()); | 271 ASSERT(m_workerGlobalScope->hasOneRef()); |
| 371 #endif | 272 #endif |
| 372 m_workerGlobalScope->notifyContextDestroyed(); | 273 m_workerGlobalScope->notifyContextDestroyed(); |
| 373 m_workerGlobalScope = nullptr; | 274 m_workerGlobalScope = nullptr; |
| 374 | 275 |
| 375 backingThread().removeTaskObserver(m_microtaskRunner.get()); | 276 backingThread().removeTaskObserver(m_microtaskRunner.get()); |
| 376 backingThread().shutdown(); | 277 backingThread().shutdown(); |
| 377 destroyIsolate(); | 278 destroyIsolate(); |
| 378 | 279 |
| 379 m_microtaskRunner = nullptr; | 280 m_microtaskRunner = nullptr; |
| 380 | 281 |
| 381 // Notify the proxy that the WorkerGlobalScope has been disposed of. | 282 // Notify the proxy that the WorkerGlobalScope has been disposed of. |
| 382 // This can free this thread object, hence it must not be touched afterwards
. | 283 // This can free this thread object, hence it must not be touched afterwards
. |
| 383 workerReportingProxy().workerThreadTerminated(); | 284 workerReportingProxy().workerThreadTerminated(); |
| 384 | 285 |
| 385 m_terminationEvent->signal(); | 286 m_terminationEvent->signal(); |
| 386 | |
| 387 // Clean up PlatformThreadData before WTF::WTFThreadData goes away! | |
| 388 PlatformThreadData::current().destroy(); | |
| 389 } | 287 } |
| 390 | 288 |
| 391 | 289 |
| 392 void WorkerThread::stop() | 290 void WorkerThread::stop() |
| 393 { | 291 { |
| 394 // Prevent the deadlock between GC and an attempt to stop a thread. | 292 // Prevent the deadlock between GC and an attempt to stop a thread. |
| 395 SafePointScope safePointScope(ThreadState::HeapPointersOnStack); | 293 SafePointScope safePointScope(ThreadState::HeapPointersOnStack); |
| 396 stopInternal(); | 294 stopInternal(); |
| 397 } | 295 } |
| 398 | 296 |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); | 478 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); |
| 581 } | 479 } |
| 582 | 480 |
| 583 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) | 481 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) |
| 584 { | 482 { |
| 585 MutexLocker locker(m_workerInspectorControllerMutex); | 483 MutexLocker locker(m_workerInspectorControllerMutex); |
| 586 m_workerInspectorController = workerInspectorController; | 484 m_workerInspectorController = workerInspectorController; |
| 587 } | 485 } |
| 588 | 486 |
| 589 } // namespace blink | 487 } // namespace blink |
| OLD | NEW |