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 |