Chromium Code Reviews| 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 27 matching lines...) Expand all Loading... | |
| 38 #include "core/workers/WorkerThreadStartupData.h" | 38 #include "core/workers/WorkerThreadStartupData.h" |
| 39 #include "platform/PlatformThreadData.h" | 39 #include "platform/PlatformThreadData.h" |
| 40 #include "platform/Task.h" | 40 #include "platform/Task.h" |
| 41 #include "platform/ThreadTimers.h" | 41 #include "platform/ThreadTimers.h" |
| 42 #include "platform/heap/ThreadState.h" | 42 #include "platform/heap/ThreadState.h" |
| 43 #include "platform/weborigin/KURL.h" | 43 #include "platform/weborigin/KURL.h" |
| 44 #include "public/platform/Platform.h" | 44 #include "public/platform/Platform.h" |
| 45 #include "public/platform/WebThread.h" | 45 #include "public/platform/WebThread.h" |
| 46 #include "public/platform/WebWaitableEvent.h" | 46 #include "public/platform/WebWaitableEvent.h" |
| 47 #include "public/platform/WebWorkerRunLoop.h" | 47 #include "public/platform/WebWorkerRunLoop.h" |
| 48 #include "wtf/Noncopyable.h" | 48 #include "wtf/Atomics.h" |
| 49 #include "wtf/text/WTFString.h" | 49 #include "wtf/text/WTFString.h" |
| 50 | 50 |
| 51 #include <utility> | 51 #include <utility> |
| 52 | 52 |
| 53 namespace blink { | 53 namespace blink { |
| 54 | 54 |
| 55 namespace { | 55 namespace { |
| 56 const int64 kShortIdleHandlerDelayMs = 1000; | 56 const int64 kShortIdleHandlerDelayMs = 1000; |
| 57 const int64 kLongIdleHandlerDelayMs = 10*1000; | 57 const int64 kLongIdleHandlerDelayMs = 10*1000; |
| 58 | 58 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 171 m_sharedTimerFunction(); | 171 m_sharedTimerFunction(); |
| 172 } | 172 } |
| 173 | 173 |
| 174 WorkerThread* m_workerThread; | 174 WorkerThread* m_workerThread; |
| 175 SharedTimerFunction m_sharedTimerFunction; | 175 SharedTimerFunction m_sharedTimerFunction; |
| 176 double m_nextFireTime; | 176 double m_nextFireTime; |
| 177 bool m_running; | 177 bool m_running; |
| 178 WorkerThreadCancelableTask* m_lastQueuedTask; | 178 WorkerThreadCancelableTask* m_lastQueuedTask; |
| 179 }; | 179 }; |
| 180 | 180 |
| 181 class WorkerThreadTask : public blink::WebThread::Task { | 181 // WorkerThreadTask made private to WorkerThread |
| 182 WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED; | |
| 183 public: | |
| 184 static PassOwnPtr<WorkerThreadTask> create(WorkerThread& workerThread, PassO wnPtr<ExecutionContextTask> task, bool isInstrumented) | |
| 185 { | |
| 186 return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented) ); | |
| 187 } | |
| 188 | 182 |
| 189 virtual ~WorkerThreadTask() { } | 183 PassOwnPtr<WorkerThread::WorkerThreadTask> WorkerThread::WorkerThreadTask::creat e(WorkerThread& workerThread |
| 184 , PassOwnPtr<ExecutionContextTask> task, bool isInstrumented) | |
| 185 { | |
| 186 return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented)); | |
| 187 } | |
| 190 | 188 |
| 191 virtual void run() OVERRIDE | 189 void WorkerThread::WorkerThreadTask::run() |
| 192 { | 190 { |
| 193 WorkerGlobalScope* workerGlobalScope = m_workerThread.workerGlobalScope( ); | 191 WorkerGlobalScope* workerGlobalScope = m_workerThread.workerGlobalScope(); |
| 194 // Tasks could be put on the message loop after the cleanup task, | 192 // Tasks could be put on the message loop after the cleanup task, |
| 195 // ensure none of those are ran. | 193 // ensure none of those are ran. |
| 196 if (!workerGlobalScope) | 194 if (!workerGlobalScope) |
| 197 return; | 195 return; |
| 198 | 196 |
| 199 if (m_isInstrumented) | 197 if (m_isInstrumented) |
| 200 InspectorInstrumentation::willPerformExecutionContextTask(workerGlob alScope, m_task.get()); | 198 InspectorInstrumentation::willPerformExecutionContextTask(workerGlobalSc ope, m_task.get()); |
| 201 if ((!workerGlobalScope->isClosing() && !m_workerThread.terminated()) || m_task->isCleanupTask()) | 199 if ((!workerGlobalScope->isClosing() && !m_workerThread.terminated()) || m_t ask->isCleanupTask()) |
| 200 if (!m_isIdleHandlerTask || (m_isIdleHandlerTask && !m_workerThread.task Count())) { | |
| 202 m_task->performTask(workerGlobalScope); | 201 m_task->performTask(workerGlobalScope); |
| 203 if (m_isInstrumented) | 202 } |
| 204 InspectorInstrumentation::didPerformExecutionContextTask(workerGloba lScope); | 203 if (m_isInstrumented) |
| 205 } | 204 InspectorInstrumentation::didPerformExecutionContextTask(workerGlobalSco pe); |
| 206 | 205 |
| 207 private: | 206 // If no more tasks are queued up after this, then queue up the idleHandler |
| 208 WorkerThreadTask(WorkerThread& workerThread, PassOwnPtr<ExecutionContextTask > task, bool isInstrumented) | 207 // to trigger GC. |
| 209 : m_workerThread(workerThread) | 208 if (!m_isIdleHandlerTask && !m_workerThread.decrementAndReturnTaskCount() |
| 210 , m_task(task) | 209 && !m_workerThread.m_IdleHandlerTaskPosted) |
|
jochen (gone - plz use gerrit)
2014/10/14 13:46:03
nit. put on previous line
| |
| 211 , m_isInstrumented(isInstrumented) | 210 m_workerThread.queueUpIdleHandlerNow(kLongIdleHandlerDelayMs); |
| 212 { | 211 } |
| 213 if (m_isInstrumented) | |
| 214 m_isInstrumented = !m_task->taskNameForInstrumentation().isEmpty(); | |
| 215 if (m_isInstrumented) | |
| 216 InspectorInstrumentation::didPostExecutionContextTask(m_workerThread .workerGlobalScope(), m_task.get()); | |
| 217 } | |
| 218 | 212 |
| 219 WorkerThread& m_workerThread; | 213 WorkerThread::WorkerThreadTask::WorkerThreadTask(WorkerThread& workerThread |
| 220 OwnPtr<ExecutionContextTask> m_task; | 214 , PassOwnPtr<ExecutionContextTask> task, bool isInstrumented) |
| 221 bool m_isInstrumented; | 215 : m_workerThread(workerThread) |
| 222 }; | 216 , m_task(task) |
| 217 , m_isInstrumented(isInstrumented) | |
| 218 , m_isIdleHandlerTask(false) | |
| 219 { | |
| 220 if (m_isInstrumented) | |
| 221 m_isInstrumented = !m_task->taskNameForInstrumentation().isEmpty(); | |
| 222 if (m_isInstrumented) | |
| 223 InspectorInstrumentation::didPostExecutionContextTask(m_workerThread.wor kerGlobalScope(), m_task.get()); | |
| 224 } | |
| 223 | 225 |
| 224 class RunDebuggerQueueTask FINAL : public ExecutionContextTask { | 226 class RunDebuggerQueueTask FINAL : public ExecutionContextTask { |
| 225 public: | 227 public: |
| 226 static PassOwnPtr<RunDebuggerQueueTask> create(WorkerThread* thread) | 228 static PassOwnPtr<RunDebuggerQueueTask> create(WorkerThread* thread) |
| 227 { | 229 { |
| 228 return adoptPtr(new RunDebuggerQueueTask(thread)); | 230 return adoptPtr(new RunDebuggerQueueTask(thread)); |
| 229 } | 231 } |
| 230 virtual void performTask(ExecutionContext* context) OVERRIDE | 232 virtual void performTask(ExecutionContext* context) OVERRIDE |
| 231 { | 233 { |
| 232 ASSERT(context->isWorkerGlobalScope()); | 234 ASSERT(context->isWorkerGlobalScope()); |
| 233 m_thread->runDebuggerTask(WorkerThread::DontWaitForMessage); | 235 m_thread->runDebuggerTask(WorkerThread::DontWaitForMessage); |
| 234 } | 236 } |
| 235 | 237 |
| 236 private: | 238 private: |
| 237 explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { } | 239 explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { } |
| 238 | 240 |
| 239 WorkerThread* m_thread; | 241 WorkerThread* m_thread; |
| 240 }; | 242 }; |
| 241 | 243 |
| 242 WorkerThread::WorkerThread(WorkerLoaderProxy& workerLoaderProxy, WorkerReporting Proxy& workerReportingProxy, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData> sta rtupData) | 244 WorkerThread::WorkerThread(WorkerLoaderProxy& workerLoaderProxy, WorkerReporting Proxy& workerReportingProxy, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData> sta rtupData) |
| 243 : m_terminated(false) | 245 : m_terminated(false) |
| 244 , m_workerLoaderProxy(workerLoaderProxy) | 246 , m_workerLoaderProxy(workerLoaderProxy) |
| 245 , m_workerReportingProxy(workerReportingProxy) | 247 , m_workerReportingProxy(workerReportingProxy) |
| 246 , m_startupData(startupData) | 248 , m_startupData(startupData) |
| 247 , m_shutdownEvent(adoptPtr(blink::Platform::current()->createWaitableEvent() )) | 249 , m_shutdownEvent(adoptPtr(blink::Platform::current()->createWaitableEvent() )) |
| 248 , m_terminationEvent(adoptPtr(blink::Platform::current()->createWaitableEven t())) | 250 , m_terminationEvent(adoptPtr(blink::Platform::current()->createWaitableEven t())) |
| 251 , m_IdleHandlerTaskPosted(false) | |
| 252 , m_tasksCount(0) | |
| 249 { | 253 { |
| 250 MutexLocker lock(threadSetMutex()); | 254 MutexLocker lock(threadSetMutex()); |
| 251 workerThreads().add(this); | 255 workerThreads().add(this); |
| 252 } | 256 } |
| 253 | 257 |
| 254 WorkerThread::~WorkerThread() | 258 WorkerThread::~WorkerThread() |
| 255 { | 259 { |
| 256 MutexLocker lock(threadSetMutex()); | 260 MutexLocker lock(threadSetMutex()); |
| 257 ASSERT(workerThreads().contains(this)); | 261 ASSERT(workerThreads().contains(this)); |
| 258 workerThreads().remove(this); | 262 workerThreads().remove(this); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 314 // Notify proxy that a new WorkerGlobalScope has been created and started. | 318 // Notify proxy that a new WorkerGlobalScope has been created and started. |
| 315 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get()); | 319 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get()); |
| 316 | 320 |
| 317 WorkerScriptController* script = m_workerGlobalScope->script(); | 321 WorkerScriptController* script = m_workerGlobalScope->script(); |
| 318 if (!script->isExecutionForbidden()) | 322 if (!script->isExecutionForbidden()) |
| 319 script->initializeContextIfNeeded(); | 323 script->initializeContextIfNeeded(); |
| 320 InspectorInstrumentation::willEvaluateWorkerScript(workerGlobalScope(), star tMode); | 324 InspectorInstrumentation::willEvaluateWorkerScript(workerGlobalScope(), star tMode); |
| 321 script->evaluate(ScriptSourceCode(sourceCode, scriptURL)); | 325 script->evaluate(ScriptSourceCode(sourceCode, scriptURL)); |
| 322 | 326 |
| 323 postInitialize(); | 327 postInitialize(); |
| 324 | |
| 325 postDelayedTask(createSameThreadTask(&WorkerThread::idleHandler, this), kSho rtIdleHandlerDelayMs); | |
| 326 } | 328 } |
| 327 | 329 |
| 328 void WorkerThread::cleanup() | 330 void WorkerThread::cleanup() |
| 329 { | 331 { |
| 330 | 332 |
| 331 // This should be called before we start the shutdown procedure. | 333 // This should be called before we start the shutdown procedure. |
| 332 workerReportingProxy().willDestroyWorkerGlobalScope(); | 334 workerReportingProxy().willDestroyWorkerGlobalScope(); |
| 333 | 335 |
| 334 // The below assignment will destroy the context, which will in turn notify messaging proxy. | 336 // The below assignment will destroy the context, which will in turn notify messaging proxy. |
| 335 // We cannot let any objects survive past thread exit, because no other thre ad will run GC or otherwise destroy them. | 337 // We cannot let any objects survive past thread exit, because no other thre ad will run GC or otherwise destroy them. |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 452 | 454 |
| 453 for (HashSet<WorkerThread*>::iterator itr = threads.begin(); itr != threads. end(); ++itr) | 455 for (HashSet<WorkerThread*>::iterator itr = threads.begin(); itr != threads. end(); ++itr) |
| 454 (*itr)->terminationEvent()->wait(); | 456 (*itr)->terminationEvent()->wait(); |
| 455 } | 457 } |
| 456 | 458 |
| 457 bool WorkerThread::isCurrentThread() const | 459 bool WorkerThread::isCurrentThread() const |
| 458 { | 460 { |
| 459 return m_thread && m_thread->isCurrentThread(); | 461 return m_thread && m_thread->isCurrentThread(); |
| 460 } | 462 } |
| 461 | 463 |
| 464 void WorkerThread::queueUpIdleHandlerNow(long long delayMs) | |
| 465 { | |
| 466 OwnPtr<WorkerThreadTask> idleHandlerTask = WorkerThreadTask::create(*this, | |
|
jochen (gone - plz use gerrit)
2014/10/14 13:46:03
nit, put on one line
Mayur Kankanwadi
2014/11/04 06:36:58
Done.
| |
| 467 createSameThreadTask(&WorkerThread::idleHandler, this), true); | |
| 468 idleHandlerTask.get()->setIsIdleHandlerTask(true); | |
|
jochen (gone - plz use gerrit)
2014/10/14 13:46:03
should work without get()
Mayur Kankanwadi
2014/11/04 06:36:58
Done.
| |
| 469 m_thread->postDelayedTask(idleHandlerTask.leakPtr(), delayMs); | |
| 470 m_IdleHandlerTaskPosted = true; | |
| 471 } | |
| 472 | |
| 462 void WorkerThread::idleHandler() | 473 void WorkerThread::idleHandler() |
| 463 { | 474 { |
| 464 ASSERT(m_workerGlobalScope.get()); | 475 ASSERT(m_workerGlobalScope.get()); |
| 465 int64 delay = kLongIdleHandlerDelayMs; | 476 int64 delay = kLongIdleHandlerDelayMs; |
| 466 | 477 |
| 478 // Some tasks may have been started in the mean time, so lets return back | |
| 479 // and wait for the next idleHandler to be fired. | |
| 480 if (m_tasksCount) { | |
| 481 m_IdleHandlerTaskPosted = false; | |
|
jochen (gone - plz use gerrit)
2014/10/14 13:46:03
nit. move this up outside the if()
Mayur Kankanwadi
2014/11/04 06:36:58
Done.
| |
| 482 return; | |
| 483 } | |
| 467 // Do a script engine idle notification if the next event is distant enough. | 484 // Do a script engine idle notification if the next event is distant enough. |
| 468 const double kMinIdleTimespan = 0.3; | 485 const double kMinIdleTimespan = 0.3; |
| 486 // This is set to true when idleNotification returns false. | |
| 487 // idleNotification returns false only when more GC is required. It returns | |
| 488 // true if no more GC is required and that is when callGCAgain will be set t o false. | |
| 489 bool callGCAgain = false; | |
| 469 if (m_sharedTimer->nextFireTime() == 0.0 || m_sharedTimer->nextFireTime() > currentTime() + kMinIdleTimespan) { | 490 if (m_sharedTimer->nextFireTime() == 0.0 || m_sharedTimer->nextFireTime() > currentTime() + kMinIdleTimespan) { |
| 470 bool hasMoreWork = !m_workerGlobalScope->idleNotification(); | 491 callGCAgain = !m_workerGlobalScope->idleNotification(); |
| 471 if (hasMoreWork) | 492 if (callGCAgain) |
| 472 delay = kShortIdleHandlerDelayMs; | 493 delay = kShortIdleHandlerDelayMs; |
| 473 } | 494 } |
| 495 if (callGCAgain) | |
| 496 queueUpIdleHandlerNow(delay); | |
|
jochen (gone - plz use gerrit)
2014/10/14 13:46:03
should be 0
| |
| 497 else | |
| 498 m_IdleHandlerTaskPosted = false; | |
|
jochen (gone - plz use gerrit)
2014/10/14 13:46:03
not needed anymore after the one above is mvoed
Mayur Kankanwadi
2014/11/04 06:36:58
Done.
| |
| 499 } | |
| 474 | 500 |
| 475 postDelayedTask(createSameThreadTask(&WorkerThread::idleHandler, this), dela y); | 501 int WorkerThread::decrementAndReturnTaskCount() |
| 502 { | |
| 503 atomicDecrement(&m_tasksCount); | |
| 504 return m_tasksCount; | |
| 476 } | 505 } |
| 477 | 506 |
| 478 void WorkerThread::postTask(PassOwnPtr<ExecutionContextTask> task) | 507 void WorkerThread::postTask(PassOwnPtr<ExecutionContextTask> task) |
| 479 { | 508 { |
| 509 atomicIncrement(&m_tasksCount); | |
| 480 m_thread->postTask(WorkerThreadTask::create(*this, task, true).leakPtr()); | 510 m_thread->postTask(WorkerThreadTask::create(*this, task, true).leakPtr()); |
| 481 } | 511 } |
| 482 | 512 |
| 483 void WorkerThread::postDelayedTask(PassOwnPtr<ExecutionContextTask> task, long l ong delayMs) | 513 void WorkerThread::postDelayedTask(PassOwnPtr<ExecutionContextTask> task, long l ong delayMs) |
| 484 { | 514 { |
| 515 atomicIncrement(&m_tasksCount); | |
| 485 m_thread->postDelayedTask(WorkerThreadTask::create(*this, task, true).leakPt r(), delayMs); | 516 m_thread->postDelayedTask(WorkerThreadTask::create(*this, task, true).leakPt r(), delayMs); |
| 486 } | 517 } |
| 487 | 518 |
| 488 void WorkerThread::postDebuggerTask(PassOwnPtr<ExecutionContextTask> task) | 519 void WorkerThread::postDebuggerTask(PassOwnPtr<ExecutionContextTask> task) |
| 489 { | 520 { |
| 490 m_debuggerMessageQueue.append(WorkerThreadTask::create(*this, task, false)); | 521 m_debuggerMessageQueue.append(WorkerThreadTask::create(*this, task, false)); |
| 491 postTask(RunDebuggerQueueTask::create(this)); | 522 postTask(RunDebuggerQueueTask::create(this)); |
| 492 } | 523 } |
| 493 | 524 |
| 494 MessageQueueWaitResult WorkerThread::runDebuggerTask(WaitMode waitMode) | 525 MessageQueueWaitResult WorkerThread::runDebuggerTask(WaitMode waitMode) |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 523 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); | 554 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); |
| 524 } | 555 } |
| 525 | 556 |
| 526 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke rInspectorController) | 557 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke rInspectorController) |
| 527 { | 558 { |
| 528 MutexLocker locker(m_workerInspectorControllerMutex); | 559 MutexLocker locker(m_workerInspectorControllerMutex); |
| 529 m_workerInspectorController = workerInspectorController; | 560 m_workerInspectorController = workerInspectorController; |
| 530 } | 561 } |
| 531 | 562 |
| 532 } // namespace blink | 563 } // namespace blink |
| OLD | NEW |