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 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 return; | 249 return; |
346 } | 250 } |
347 | 251 |
348 m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this)); | 252 m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this)); |
349 backingThread().addTaskObserver(m_microtaskRunner.get()); | 253 backingThread().addTaskObserver(m_microtaskRunner.get()); |
350 backingThread().initialize(); | 254 backingThread().initialize(); |
351 | 255 |
352 m_isolate = initializeIsolate(); | 256 m_isolate = initializeIsolate(); |
353 m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release()); | 257 m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release()); |
354 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge
t() ? cachedMetaData->size() : 0); | 258 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge
t() ? cachedMetaData->size() : 0); |
355 | |
356 PlatformThreadData::current().threadTimers().setSharedTimer(adoptPtr(new
WorkerSharedTimer(this))); | |
357 } | 259 } |
358 | 260 |
359 // The corresponding call to stopRunLoop() is in ~WorkerScriptController(). | 261 // The corresponding call to stopRunLoop() is in ~WorkerScriptController(). |
360 didStartRunLoop(); | 262 didStartRunLoop(); |
361 | 263 |
362 // Notify proxy that a new WorkerGlobalScope has been created and started. | 264 // Notify proxy that a new WorkerGlobalScope has been created and started. |
363 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get()); | 265 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get()); |
364 | 266 |
365 WorkerScriptController* script = m_workerGlobalScope->script(); | 267 WorkerScriptController* script = m_workerGlobalScope->script(); |
366 if (!script->isExecutionForbidden()) | 268 if (!script->isExecutionForbidden()) |
367 script->initializeContextIfNeeded(); | 269 script->initializeContextIfNeeded(); |
368 if (startMode == PauseWorkerGlobalScopeOnStart) | 270 if (startMode == PauseWorkerGlobalScopeOnStart) |
369 m_workerGlobalScope->workerInspectorController()->pauseOnStart(); | 271 m_workerGlobalScope->workerInspectorController()->pauseOnStart(); |
370 | 272 |
371 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip
tCachedMetadataHandler(scriptURL, cachedMetaData.get())); | 273 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip
tCachedMetadataHandler(scriptURL, cachedMetaData.get())); |
372 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul
lptr, handler.get(), v8CacheOptions); | 274 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul
lptr, handler.get(), v8CacheOptions); |
373 m_workerGlobalScope->didEvaluateWorkerScript(); | 275 m_workerGlobalScope->didEvaluateWorkerScript(); |
374 m_workerReportingProxy.didEvaluateWorkerScript(success); | 276 m_workerReportingProxy.didEvaluateWorkerScript(success); |
375 | 277 |
376 postInitialize(); | 278 postInitialize(); |
377 | 279 |
378 m_webScheduler->postIdleTaskAfterWakeup(FROM_HERE, new WorkerThreadIdleTask(
this)); | 280 m_webScheduler->postIdleTaskAfterWakeup(FROM_HERE, new WorkerThreadIdleTask(
this)); |
379 } | 281 } |
380 | 282 |
381 void WorkerThread::shutdown() | 283 void WorkerThread::shutdown() |
382 { | 284 { |
383 MutexLocker lock(m_threadStateMutex); | 285 MutexLocker lock(m_threadStateMutex); |
384 ASSERT(isCurrentThread()); | 286 ASSERT(isCurrentThread()); |
385 | 287 |
386 PlatformThreadData::current().threadTimers().setSharedTimer(nullptr); | |
387 workerGlobalScope()->dispose(); | 288 workerGlobalScope()->dispose(); |
388 willDestroyIsolate(); | 289 willDestroyIsolate(); |
389 | 290 |
390 // This should be called before we start the shutdown procedure. | 291 // This should be called before we start the shutdown procedure. |
391 workerReportingProxy().willDestroyWorkerGlobalScope(); | 292 workerReportingProxy().willDestroyWorkerGlobalScope(); |
392 | 293 |
393 // The below assignment will destroy the context, which will in turn notify
messaging proxy. | 294 // The below assignment will destroy the context, which will in turn notify
messaging proxy. |
394 // We cannot let any objects survive past thread exit, because no other thre
ad will run GC or otherwise destroy them. | 295 // We cannot let any objects survive past thread exit, because no other thre
ad will run GC or otherwise destroy them. |
395 // If Oilpan is enabled, we detach of the context/global scope, with the fin
al heap cleanup below sweeping it out. | 296 // If Oilpan is enabled, we detach of the context/global scope, with the fin
al heap cleanup below sweeping it out. |
396 #if !ENABLE(OILPAN) | 297 #if !ENABLE(OILPAN) |
397 ASSERT(m_workerGlobalScope->hasOneRef()); | 298 ASSERT(m_workerGlobalScope->hasOneRef()); |
398 #endif | 299 #endif |
399 m_workerGlobalScope->notifyContextDestroyed(); | 300 m_workerGlobalScope->notifyContextDestroyed(); |
400 m_workerGlobalScope = nullptr; | 301 m_workerGlobalScope = nullptr; |
401 | 302 |
402 backingThread().removeTaskObserver(m_microtaskRunner.get()); | 303 backingThread().removeTaskObserver(m_microtaskRunner.get()); |
403 backingThread().shutdown(); | 304 backingThread().shutdown(); |
404 destroyIsolate(); | 305 destroyIsolate(); |
405 | 306 |
406 m_microtaskRunner = nullptr; | 307 m_microtaskRunner = nullptr; |
407 | 308 |
408 // Notify the proxy that the WorkerGlobalScope has been disposed of. | 309 // Notify the proxy that the WorkerGlobalScope has been disposed of. |
409 // This can free this thread object, hence it must not be touched afterwards
. | 310 // This can free this thread object, hence it must not be touched afterwards
. |
410 workerReportingProxy().workerThreadTerminated(); | 311 workerReportingProxy().workerThreadTerminated(); |
411 | 312 |
412 m_terminationEvent->signal(); | 313 m_terminationEvent->signal(); |
413 | |
414 // Clean up PlatformThreadData before WTF::WTFThreadData goes away! | |
415 PlatformThreadData::current().destroy(); | |
416 } | 314 } |
417 | 315 |
418 | 316 |
419 void WorkerThread::stop() | 317 void WorkerThread::stop() |
420 { | 318 { |
421 // Prevent the deadlock between GC and an attempt to stop a thread. | 319 // Prevent the deadlock between GC and an attempt to stop a thread. |
422 SafePointScope safePointScope(ThreadState::HeapPointersOnStack); | 320 SafePointScope safePointScope(ThreadState::HeapPointersOnStack); |
423 stopInternal(); | 321 stopInternal(); |
424 } | 322 } |
425 | 323 |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); | 499 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); |
602 } | 500 } |
603 | 501 |
604 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) | 502 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) |
605 { | 503 { |
606 MutexLocker locker(m_workerInspectorControllerMutex); | 504 MutexLocker locker(m_workerInspectorControllerMutex); |
607 m_workerInspectorController = workerInspectorController; | 505 m_workerInspectorController = workerInspectorController; |
608 } | 506 } |
609 | 507 |
610 } // namespace blink | 508 } // namespace blink |
OLD | NEW |