Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: Source/core/workers/WorkerThread.cpp

Issue 956333002: Refactor TimeBase to post tasks. Workers to use real Idle tasks. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Rebase Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/workers/WorkerThread.h ('k') | Source/core/workers/WorkerThreadTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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"
47 #include "public/platform/WebScheduler.h"
49 #include "public/platform/WebThread.h" 48 #include "public/platform/WebThread.h"
50 #include "public/platform/WebWaitableEvent.h" 49 #include "public/platform/WebWaitableEvent.h"
51 #include "wtf/Noncopyable.h" 50 #include "wtf/Noncopyable.h"
52 #include "wtf/WeakPtr.h" 51 #include "wtf/WeakPtr.h"
53 #include "wtf/text/WTFString.h" 52 #include "wtf/text/WTFString.h"
54 53
55 namespace blink { 54 namespace blink {
56 55
57 namespace { 56 namespace {
58 const int64_t kShortIdleHandlerDelayMs = 1000; 57 const double kLongIdleHandlerDelaySecs = 1.0;
59 const int64_t kLongIdleHandlerDelayMs = 10*1000;
60 58
61 class MicrotaskRunner : public WebThread::TaskObserver { 59 class MicrotaskRunner : public WebThread::TaskObserver {
62 public: 60 public:
63 explicit MicrotaskRunner(WorkerThread* workerThread) 61 explicit MicrotaskRunner(WorkerThread* workerThread)
64 : m_workerThread(workerThread) 62 : m_workerThread(workerThread)
65 { 63 {
66 } 64 }
67 65
68 virtual void willProcessTask() override { } 66 virtual void willProcessTask() override { }
69 virtual void didProcessTask() override 67 virtual void didProcessTask() override
(...skipping 24 matching lines...) Expand all
94 DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ()); 92 DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ());
95 return threads; 93 return threads;
96 } 94 }
97 95
98 unsigned WorkerThread::workerThreadCount() 96 unsigned WorkerThread::workerThreadCount()
99 { 97 {
100 MutexLocker lock(threadSetMutex()); 98 MutexLocker lock(threadSetMutex());
101 return workerThreads().size(); 99 return workerThreads().size();
102 } 100 }
103 101
104 class WorkerThreadCancelableTask final : public ExecutionContextTask {
105 WTF_MAKE_NONCOPYABLE(WorkerThreadCancelableTask); WTF_MAKE_FAST_ALLOCATED(Wo rkerThreadCancelableTask);
106 public:
107 static PassOwnPtr<WorkerThreadCancelableTask> create(PassOwnPtr<Closure> clo sure)
108 {
109 return adoptPtr(new WorkerThreadCancelableTask(closure));
110 }
111
112 virtual ~WorkerThreadCancelableTask() { }
113
114 virtual void performTask(ExecutionContext*) override
115 {
116 if (!m_taskCanceled)
117 (*m_closure)();
118 }
119
120 WeakPtr<WorkerThreadCancelableTask> createWeakPtr() { return m_weakFactory.c reateWeakPtr(); }
121 void cancelTask() { m_taskCanceled = true; }
122
123 private:
124 explicit WorkerThreadCancelableTask(PassOwnPtr<Closure> closure)
125 : m_closure(closure)
126 , m_weakFactory(this)
127 , m_taskCanceled(false)
128 { }
129
130 OwnPtr<Closure> m_closure;
131 WeakPtrFactory<WorkerThreadCancelableTask> m_weakFactory;
132 bool m_taskCanceled;
133 };
134
135 class WorkerSharedTimer : public SharedTimer {
136 public:
137 explicit WorkerSharedTimer(WorkerThread* workerThread)
138 : m_workerThread(workerThread)
139 , m_running(false)
140 { }
141
142 typedef void (*SharedTimerFunction)();
143 virtual void setFiredFunction(SharedTimerFunction func)
144 {
145 m_sharedTimerFunction = func;
146 }
147
148 virtual void setFireInterval(double interval)
149 {
150 ASSERT(m_sharedTimerFunction);
151
152 // See BlinkPlatformImpl::setSharedTimerFireInterval for explanation of
153 // why ceil is used in the interval calculation.
154 int64_t delay = static_cast<int64_t>(ceil(interval * 1000));
155
156 if (delay < 0) {
157 delay = 0;
158 }
159
160 m_running = true;
161
162 if (m_lastQueuedTask.get())
163 m_lastQueuedTask->cancelTask();
164
165 // Now queue the task as a cancellable one.
166 OwnPtr<WorkerThreadCancelableTask> task = WorkerThreadCancelableTask::cr eate(bind(&WorkerSharedTimer::OnTimeout, this));
167 m_lastQueuedTask = task->createWeakPtr();
168 m_workerThread->postDelayedTask(FROM_HERE, task.release(), delay);
169 }
170
171 virtual void stop()
172 {
173 m_running = false;
174 m_lastQueuedTask = nullptr;
175 }
176
177 private:
178 void OnTimeout()
179 {
180 ASSERT(m_workerThread->workerGlobalScope());
181
182 m_lastQueuedTask = nullptr;
183
184 if (m_sharedTimerFunction && m_running && !m_workerThread->workerGlobalS cope()->isClosing())
185 m_sharedTimerFunction();
186 }
187
188 WorkerThread* m_workerThread;
189 SharedTimerFunction m_sharedTimerFunction;
190 bool m_running;
191
192 // The task to run OnTimeout, if any. While OnTimeout resets
193 // m_lastQueuedTask, this must be a weak pointer because the
194 // worker runloop may delete the task as it is shutting down.
195 WeakPtr<WorkerThreadCancelableTask> m_lastQueuedTask;
196 };
197
198 class WorkerThreadTask : public blink::WebThread::Task { 102 class WorkerThreadTask : public blink::WebThread::Task {
199 WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED(WorkerThread Task); 103 WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED(WorkerThread Task);
200 public: 104 public:
201 static PassOwnPtr<WorkerThreadTask> create(WorkerThread& workerThread, PassO wnPtr<ExecutionContextTask> task, bool isInstrumented) 105 static PassOwnPtr<WorkerThreadTask> create(WorkerThread& workerThread, PassO wnPtr<ExecutionContextTask> task, bool isInstrumented)
202 { 106 {
203 return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented) ); 107 return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented) );
204 } 108 }
205 109
206 virtual ~WorkerThreadTask() { } 110 virtual ~WorkerThreadTask() { }
207 111
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 162
259 WorkerThread::WorkerThread(const char* threadName, PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, PassOwnPtr<Worke rThreadStartupData> startupData) 163 WorkerThread::WorkerThread(const char* threadName, PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, PassOwnPtr<Worke rThreadStartupData> startupData)
260 : m_threadName(threadName) 164 : m_threadName(threadName)
261 , m_terminated(false) 165 , m_terminated(false)
262 , m_workerLoaderProxy(workerLoaderProxy) 166 , m_workerLoaderProxy(workerLoaderProxy)
263 , m_workerReportingProxy(workerReportingProxy) 167 , m_workerReportingProxy(workerReportingProxy)
264 , m_startupData(startupData) 168 , m_startupData(startupData)
265 , m_isolate(nullptr) 169 , m_isolate(nullptr)
266 , m_shutdownEvent(adoptPtr(blink::Platform::current()->createWaitableEvent() )) 170 , m_shutdownEvent(adoptPtr(blink::Platform::current()->createWaitableEvent() ))
267 , m_terminationEvent(adoptPtr(blink::Platform::current()->createWaitableEven t())) 171 , m_terminationEvent(adoptPtr(blink::Platform::current()->createWaitableEven t()))
172 , m_webScheduler(nullptr)
173 , m_preShutdown(false)
268 { 174 {
269 MutexLocker lock(threadSetMutex()); 175 MutexLocker lock(threadSetMutex());
270 workerThreads().add(this); 176 workerThreads().add(this);
271 } 177 }
272 178
273 WorkerThread::~WorkerThread() 179 WorkerThread::~WorkerThread()
274 { 180 {
275 MutexLocker lock(threadSetMutex()); 181 MutexLocker lock(threadSetMutex());
276 ASSERT(workerThreads().contains(this)); 182 ASSERT(workerThreads().contains(this));
277 workerThreads().remove(this); 183 workerThreads().remove(this);
278 } 184 }
279 185
280 void WorkerThread::start() 186 void WorkerThread::start()
281 { 187 {
282 if (m_thread) 188 if (m_thread)
283 return; 189 return;
284 190
285 m_thread = createWebThreadSupportingGC(); 191 m_thread = createWebThreadSupportingGC();
192 m_webScheduler = m_thread->platformThread().scheduler();
286 m_thread->postTask(FROM_HERE, new Task(threadSafeBind(&WorkerThread::initial ize, AllowCrossThreadAccess(this)))); 193 m_thread->postTask(FROM_HERE, new Task(threadSafeBind(&WorkerThread::initial ize, AllowCrossThreadAccess(this))));
287 } 194 }
288 195
289 void WorkerThread::interruptAndDispatchInspectorCommands() 196 void WorkerThread::interruptAndDispatchInspectorCommands()
290 { 197 {
291 MutexLocker locker(m_workerInspectorControllerMutex); 198 MutexLocker locker(m_workerInspectorControllerMutex);
292 if (m_workerInspectorController) 199 if (m_workerInspectorController)
293 m_workerInspectorController->interruptAndDispatchInspectorCommands(); 200 m_workerInspectorController->interruptAndDispatchInspectorCommands();
294 } 201 }
295 202
296 PlatformThreadId WorkerThread::platformThreadId() const 203 PlatformThreadId WorkerThread::platformThreadId() const
297 { 204 {
298 if (!m_thread) 205 if (!m_thread)
299 return 0; 206 return 0;
300 return m_thread->platformThread().threadId(); 207 return m_thread->platformThread().threadId();
301 } 208 }
302 209
210 // TODO(alexclarke): Use base::Bind instead of this class when the repo's merge. Unfortunately we
211 // can't use WTF::bind because the type-erasure for member function pointers wit h parameters is broken.
212 class WorkerThreadIdleTask : public WebThread::IdleTask {
213 public:
214 explicit WorkerThreadIdleTask(WorkerThread* thread)
215 : m_thread(thread) { }
216
217 ~WorkerThreadIdleTask() override { }
218
219 void run(double deadlineSeconds) override
220 {
221 m_thread->idleTask(deadlineSeconds);
222 }
223
224 private:
225 RawPtr<WorkerThread> m_thread; // NOT OWNED
226 };
227
303 void WorkerThread::initialize() 228 void WorkerThread::initialize()
304 { 229 {
305 KURL scriptURL = m_startupData->m_scriptURL; 230 KURL scriptURL = m_startupData->m_scriptURL;
306 String sourceCode = m_startupData->m_sourceCode; 231 String sourceCode = m_startupData->m_sourceCode;
307 WorkerThreadStartMode startMode = m_startupData->m_startMode; 232 WorkerThreadStartMode startMode = m_startupData->m_startMode;
308 OwnPtr<Vector<char>> cachedMetaData = m_startupData->m_cachedMetaData.releas e(); 233 OwnPtr<Vector<char>> cachedMetaData = m_startupData->m_cachedMetaData.releas e();
309 V8CacheOptions v8CacheOptions = m_startupData->m_v8CacheOptions; 234 V8CacheOptions v8CacheOptions = m_startupData->m_v8CacheOptions;
310 235
311 { 236 {
312 MutexLocker lock(m_threadCreationMutex); 237 MutexLocker lock(m_threadCreationMutex);
313 238
314 // The worker was terminated before the thread had a chance to run. 239 // The worker was terminated before the thread had a chance to run.
315 if (m_terminated) { 240 if (m_terminated) {
316 // Notify the proxy that the WorkerGlobalScope has been disposed of. 241 // Notify the proxy that the WorkerGlobalScope has been disposed of.
317 // This can free this thread object, hence it must not be touched af terwards. 242 // This can free this thread object, hence it must not be touched af terwards.
318 m_workerReportingProxy.workerThreadTerminated(); 243 m_workerReportingProxy.workerThreadTerminated();
319 return; 244 return;
320 } 245 }
321 246
322 m_microtaskRunner = adoptPtr(new MicrotaskRunner(this)); 247 m_microtaskRunner = adoptPtr(new MicrotaskRunner(this));
323 m_thread->addTaskObserver(m_microtaskRunner.get()); 248 m_thread->addTaskObserver(m_microtaskRunner.get());
324 m_thread->attachGC(); 249 m_thread->attachGC();
325 250
326 m_isolate = initializeIsolate(); 251 m_isolate = initializeIsolate();
327 m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release()); 252 m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release());
328 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge t() ? cachedMetaData->size() : 0); 253 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge t() ? cachedMetaData->size() : 0);
329
330 PlatformThreadData::current().threadTimers().setSharedTimer(adoptPtr(new WorkerSharedTimer(this)));
331 } 254 }
332 255
333 // The corresponding call to stopRunLoop() is in ~WorkerScriptController(). 256 // The corresponding call to stopRunLoop() is in ~WorkerScriptController().
334 didStartRunLoop(); 257 didStartRunLoop();
335 258
336 // Notify proxy that a new WorkerGlobalScope has been created and started. 259 // Notify proxy that a new WorkerGlobalScope has been created and started.
337 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get()); 260 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get());
338 261
339 WorkerScriptController* script = m_workerGlobalScope->script(); 262 WorkerScriptController* script = m_workerGlobalScope->script();
340 if (!script->isExecutionForbidden()) 263 if (!script->isExecutionForbidden())
341 script->initializeContextIfNeeded(); 264 script->initializeContextIfNeeded();
342 if (startMode == PauseWorkerGlobalScopeOnStart) 265 if (startMode == PauseWorkerGlobalScopeOnStart)
343 m_workerGlobalScope->workerInspectorController()->pauseOnStart(); 266 m_workerGlobalScope->workerInspectorController()->pauseOnStart();
344 267
345 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip tCachedMetadataHandler(scriptURL, cachedMetaData.get())); 268 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip tCachedMetadataHandler(scriptURL, cachedMetaData.get()));
346 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul lptr, handler.get(), v8CacheOptions); 269 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul lptr, handler.get(), v8CacheOptions);
347 m_workerGlobalScope->didEvaluateWorkerScript(); 270 m_workerGlobalScope->didEvaluateWorkerScript();
348 m_workerReportingProxy.didEvaluateWorkerScript(success); 271 m_workerReportingProxy.didEvaluateWorkerScript(success);
349 272
350 postInitialize(); 273 postInitialize();
351 274
352 postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler, this), kShortIdleHandlerDelayMs); 275 m_webScheduler->postIdleTaskAfterWakeup(FROM_HERE, new WorkerThreadIdleTask( this));
353 } 276 }
354 277
355 PassOwnPtr<WebThreadSupportingGC> WorkerThread::createWebThreadSupportingGC() 278 PassOwnPtr<WebThreadSupportingGC> WorkerThread::createWebThreadSupportingGC()
356 { 279 {
357 return WebThreadSupportingGC::create(m_threadName); 280 return WebThreadSupportingGC::create(m_threadName);
358 } 281 }
359 282
360 void WorkerThread::cleanup() 283 void WorkerThread::cleanup()
361 { 284 {
362 // This should be called before we start the shutdown procedure. 285 // This should be called before we start the shutdown procedure.
(...skipping 12 matching lines...) Expand all
375 destroyIsolate(); 298 destroyIsolate();
376 299
377 m_thread->removeTaskObserver(m_microtaskRunner.get()); 300 m_thread->removeTaskObserver(m_microtaskRunner.get());
378 m_microtaskRunner = nullptr; 301 m_microtaskRunner = nullptr;
379 302
380 // Notify the proxy that the WorkerGlobalScope has been disposed of. 303 // Notify the proxy that the WorkerGlobalScope has been disposed of.
381 // This can free this thread object, hence it must not be touched afterwards . 304 // This can free this thread object, hence it must not be touched afterwards .
382 workerReportingProxy().workerThreadTerminated(); 305 workerReportingProxy().workerThreadTerminated();
383 306
384 m_terminationEvent->signal(); 307 m_terminationEvent->signal();
385
386 // Clean up PlatformThreadData before WTF::WTFThreadData goes away!
387 PlatformThreadData::current().destroy();
388 } 308 }
389 309
390 class WorkerThreadShutdownFinishTask : public ExecutionContextTask { 310 class WorkerThreadShutdownFinishTask : public ExecutionContextTask {
391 public: 311 public:
392 static PassOwnPtr<WorkerThreadShutdownFinishTask> create() 312 static PassOwnPtr<WorkerThreadShutdownFinishTask> create()
393 { 313 {
394 return adoptPtr(new WorkerThreadShutdownFinishTask()); 314 return adoptPtr(new WorkerThreadShutdownFinishTask());
395 } 315 }
396 316
397 virtual void performTask(ExecutionContext *context) 317 virtual void performTask(ExecutionContext *context)
398 { 318 {
399 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); 319 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
400 workerGlobalScope->dispose(); 320 workerGlobalScope->dispose();
401 321
402 WorkerThread* workerThread = workerGlobalScope->thread(); 322 WorkerThread* workerThread = workerGlobalScope->thread();
403 workerThread->willDestroyIsolate(); 323 workerThread->willDestroyIsolate();
404 workerThread->m_thread->postTask(FROM_HERE, new Task(WTF::bind(&WorkerTh read::cleanup, workerThread))); 324 workerThread->m_webScheduler->postShutdownTask(FROM_HERE, new Task(WTF:: bind(&WorkerThread::cleanup, workerThread)), 0);
405 } 325 }
406 326
407 virtual bool isCleanupTask() const { return true; } 327 virtual bool isCleanupTask() const { return true; }
408 }; 328 };
409 329
410 class WorkerThreadShutdownStartTask : public ExecutionContextTask { 330 class WorkerThreadShutdownStartTask : public ExecutionContextTask {
411 public: 331 public:
412 static PassOwnPtr<WorkerThreadShutdownStartTask> create() 332 static PassOwnPtr<WorkerThreadShutdownStartTask> create()
413 { 333 {
414 return adoptPtr(new WorkerThreadShutdownStartTask()); 334 return adoptPtr(new WorkerThreadShutdownStartTask());
415 } 335 }
416 336
417 virtual void performTask(ExecutionContext *context) 337 virtual void performTask(ExecutionContext *context)
418 { 338 {
419 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); 339 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
420 workerGlobalScope->stopActiveDOMObjects(); 340 workerGlobalScope->stopActiveDOMObjects();
421 PlatformThreadData::current().threadTimers().setSharedTimer(nullptr);
422 341
423 // Event listeners would keep DOMWrapperWorld objects alive for too long . Also, they have references to JS objects, 342 // Event listeners would keep DOMWrapperWorld objects alive for too long . Also, they have references to JS objects,
424 // which become dangling once Heap is destroyed. 343 // which become dangling once Heap is destroyed.
425 workerGlobalScope->removeAllEventListeners(); 344 workerGlobalScope->removeAllEventListeners();
426 345
427 // Stick a shutdown command at the end of the queue, so that we deal 346 // Stick a shutdown command at the end of the queue, so that we deal
428 // with all the cleanup tasks the databases post first. 347 // with all the cleanup tasks the databases post first.
429 workerGlobalScope->postTask(FROM_HERE, WorkerThreadShutdownFinishTask::c reate()); 348 workerGlobalScope->postTask(FROM_HERE, WorkerThreadShutdownFinishTask::c reate());
430 } 349 }
431 350
432 virtual bool isCleanupTask() const { return true; } 351 virtual bool isCleanupTask() const { return true; }
433 }; 352 };
434 353
354 class PreShutDownTask : public WebThread::Task {
355 public:
356 PreShutDownTask(WebWaitableEvent* completion, WebScheduler* webScheduler)
357 : m_completion(completion)
358 , m_webScheduler(webScheduler) { }
359
360 ~PreShutDownTask() override { }
361
362 void run()
363 {
364 m_webScheduler->preShutdown();
365 m_completion->signal();
366 }
367
368 private:
369 RawPtr<WebWaitableEvent> m_completion; // NOT OWNED.
370 RawPtr<WebScheduler> m_webScheduler; // NOT OWNED.
371 };
372
373 void WorkerThread::preShutdown()
374 {
375 MutexLocker lock(m_preShutdownMutex);
376 if (m_preShutdown || !m_webScheduler)
377 return;
378 m_preShutdown = true;
379
380 if (m_thread->isCurrentThread()) {
381 m_webScheduler->preShutdown();
382 } else {
383 OwnPtr<WebWaitableEvent> completion(adoptPtr(blink::Platform::current()- >createWaitableEvent()));
384 m_thread->postTask(FROM_HERE, new PreShutDownTask(completion.get(), m_we bScheduler.get()));
385 completion->wait();
386 }
387 }
388
435 void WorkerThread::stop() 389 void WorkerThread::stop()
436 { 390 {
437 // Prevent the deadlock between GC and an attempt to stop a thread. 391 // Prevent the deadlock between GC and an attempt to stop a thread.
438 SafePointScope safePointScope(ThreadState::HeapPointersOnStack); 392 SafePointScope safePointScope(ThreadState::HeapPointersOnStack);
439 stopInternal(); 393 stopInternal();
440 } 394 }
441 395
442 void WorkerThread::stopInShutdownSequence() 396 void WorkerThread::stopInShutdownSequence()
443 { 397 {
444 stopInternal(); 398 stopInternal();
445 } 399 }
446 400
447 void WorkerThread::terminateAndWait() 401 void WorkerThread::terminateAndWait()
448 { 402 {
449 stop(); 403 stop();
450 m_terminationEvent->wait(); 404 m_terminationEvent->wait();
451 } 405 }
452 406
453 bool WorkerThread::terminated() 407 bool WorkerThread::terminated()
454 { 408 {
455 MutexLocker lock(m_threadCreationMutex); 409 MutexLocker lock(m_threadCreationMutex);
456 return m_terminated; 410 return m_terminated;
457 } 411 }
458 412
459 void WorkerThread::stopInternal() 413 void WorkerThread::stopInternal()
460 { 414 {
461 // Protect against this method and initialize() racing each other. 415 // Protect against this method and initialize() racing each other.
462 MutexLocker lock(m_threadCreationMutex); 416 {
417 MutexLocker lock(m_threadCreationMutex);
463 418
464 // If stop has already been called, just return. 419 // If stop has already been called, just return.
465 if (m_terminated) 420 if (m_terminated)
466 return; 421 return;
467 m_terminated = true; 422 m_terminated = true;
468 423
469 // Signal the thread to notify that the thread's stopping. 424 // Signal the thread to notify that the thread's stopping.
470 if (m_shutdownEvent) 425 if (m_shutdownEvent)
471 m_shutdownEvent->signal(); 426 m_shutdownEvent->signal();
472 427
473 if (!m_workerGlobalScope) 428 if (!m_workerGlobalScope)
474 return; 429 return;
475 430
476 // 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. 431 // Ensure that tasks are being handled by thread event loop. If script e xecution weren't forbidden, a while(1) loop in JS could keep the thread alive fo rever.
477 terminateV8Execution(); 432 terminateV8Execution();
478 433
479 InspectorInstrumentation::didKillAllExecutionContextTasks(m_workerGlobalScop e.get()); 434 InspectorInstrumentation::didKillAllExecutionContextTasks(m_workerGlobal Scope.get());
480 m_debuggerMessageQueue.kill(); 435 m_debuggerMessageQueue.kill();
481 postTask(FROM_HERE, WorkerThreadShutdownStartTask::create()); 436 postTask(FROM_HERE, WorkerThreadShutdownStartTask::create());
437 }
438 // Prevent further execution of non-shutdown tasks on the thread. Must happ en after any v8 task has been terminated.
439 preShutdown();
482 } 440 }
483 441
484 void WorkerThread::didStartRunLoop() 442 void WorkerThread::didStartRunLoop()
485 { 443 {
486 ASSERT(isCurrentThread()); 444 ASSERT(isCurrentThread());
487 blink::Platform::current()->didStartWorkerRunLoop(); 445 blink::Platform::current()->didStartWorkerRunLoop();
488 } 446 }
489 447
490 void WorkerThread::didStopRunLoop() 448 void WorkerThread::didStopRunLoop()
491 { 449 {
(...skipping 11 matching lines...) Expand all
503 461
504 for (WorkerThread* thread : threads) 462 for (WorkerThread* thread : threads)
505 thread->terminationEvent()->wait(); 463 thread->terminationEvent()->wait();
506 } 464 }
507 465
508 bool WorkerThread::isCurrentThread() const 466 bool WorkerThread::isCurrentThread() const
509 { 467 {
510 return m_thread && m_thread->isCurrentThread(); 468 return m_thread && m_thread->isCurrentThread();
511 } 469 }
512 470
513 void WorkerThread::idleHandler() 471 void WorkerThread::idleTask(double deadlineSeconds)
514 { 472 {
515 ASSERT(m_workerGlobalScope.get()); 473 if (terminated())
516 int64_t delay = kLongIdleHandlerDelayMs; 474 return;
517 475
518 // Do a script engine idle notification if the next event is distant enough. 476 double gcDeadlineSeconds = deadlineSeconds;
519 const double kMinIdleTimespan = 0.3;
520 const double nextFireTime = PlatformThreadData::current().threadTimers().nex tFireTime();
521 if (nextFireTime == 0.0 || nextFireTime > currentTime() + kMinIdleTimespan) {
522 bool hasMoreWork = !isolate()->IdleNotificationDeadline(Platform::curren t()->monotonicallyIncreasingTime() + 1.0);
523 if (hasMoreWork)
524 delay = kShortIdleHandlerDelayMs;
525 }
526 477
527 postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler, this), delay); 478 // The V8 GC does some GC steps (e.g. compaction) only when the idle notific ation is ~1s.
479 // TODO(rmcilroy): Refactor so extending the deadline like this this isn't n eeded.
480 if (m_webScheduler->canExceedIdleDeadlineIfRequired())
481 gcDeadlineSeconds = Platform::current()->monotonicallyIncreasingTime() + kLongIdleHandlerDelaySecs;
482
483 if (doIdleGc(gcDeadlineSeconds))
484 m_webScheduler->postIdleTaskAfterWakeup(FROM_HERE, new WorkerThreadIdleT ask(this));
485 else
486 m_webScheduler->postIdleTask(FROM_HERE, new WorkerThreadIdleTask(this));
487 }
488
489 bool WorkerThread::doIdleGc(double deadlineSeconds)
490 {
491 bool gcFinished = false;
492 if (deadlineSeconds > Platform::current()->monotonicallyIncreasingTime())
493 gcFinished = isolate()->IdleNotificationDeadline(deadlineSeconds);
494 return gcFinished;
528 } 495 }
529 496
530 void WorkerThread::postTask(const WebTraceLocation& location, PassOwnPtr<Executi onContextTask> task) 497 void WorkerThread::postTask(const WebTraceLocation& location, PassOwnPtr<Executi onContextTask> task)
531 { 498 {
532 m_thread->postTask(location, WorkerThreadTask::create(*this, task, true).lea kPtr()); 499 if (task->isCleanupTask())
500 m_webScheduler->postShutdownTask(location, WorkerThreadTask::create(*thi s, task, true).leakPtr(), 0);
501 else
502 m_thread->postTask(location, WorkerThreadTask::create(*this, task, true) .leakPtr());
533 } 503 }
534 504
535 void WorkerThread::postDelayedTask(const WebTraceLocation& location, PassOwnPtr< ExecutionContextTask> task, long long delayMs) 505 void WorkerThread::postDelayedTask(const WebTraceLocation& location, PassOwnPtr< ExecutionContextTask> task, long long delayMs)
536 { 506 {
537 m_thread->postDelayedTask(location, WorkerThreadTask::create(*this, task, tr ue).leakPtr(), delayMs); 507 if (task->isCleanupTask())
508 m_webScheduler->postShutdownTask(location, WorkerThreadTask::create(*thi s, task, true).leakPtr(), delayMs);
509 else
510 m_thread->postDelayedTask(location, WorkerThreadTask::create(*this, task , true).leakPtr(), delayMs);
538 } 511 }
539 512
540 v8::Isolate* WorkerThread::initializeIsolate() 513 v8::Isolate* WorkerThread::initializeIsolate()
541 { 514 {
542 ASSERT(isCurrentThread()); 515 ASSERT(isCurrentThread());
543 ASSERT(!m_isolate); 516 ASSERT(!m_isolate);
544 v8::Isolate* isolate = V8PerIsolateData::initialize(); 517 v8::Isolate* isolate = V8PerIsolateData::initialize();
545 V8Initializer::initializeWorker(isolate); 518 V8Initializer::initializeWorker(isolate);
546 519
547 m_interruptor = adoptPtr(new V8IsolateInterruptor(isolate)); 520 m_interruptor = adoptPtr(new V8IsolateInterruptor(isolate));
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
611 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); 584 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get());
612 } 585 }
613 586
614 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke rInspectorController) 587 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke rInspectorController)
615 { 588 {
616 MutexLocker locker(m_workerInspectorControllerMutex); 589 MutexLocker locker(m_workerInspectorControllerMutex);
617 m_workerInspectorController = workerInspectorController; 590 m_workerInspectorController = workerInspectorController;
618 } 591 }
619 592
620 } // namespace blink 593 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/workers/WorkerThread.h ('k') | Source/core/workers/WorkerThreadTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698