Chromium Code Reviews| Index: Source/core/workers/WorkerThread.cpp |
| diff --git a/Source/core/workers/WorkerThread.cpp b/Source/core/workers/WorkerThread.cpp |
| index 8832399a59bd08bf883af07249593c1d2ea2534f..6819793790d71efbfa2a69a30d9f7994bed03421 100644 |
| --- a/Source/core/workers/WorkerThread.cpp |
| +++ b/Source/core/workers/WorkerThread.cpp |
| @@ -45,7 +45,7 @@ |
| #include "public/platform/WebThread.h" |
| #include "public/platform/WebWaitableEvent.h" |
| #include "public/platform/WebWorkerRunLoop.h" |
| -#include "wtf/Noncopyable.h" |
| +#include "wtf/Atomics.h" |
| #include "wtf/text/WTFString.h" |
| #include <utility> |
| @@ -178,48 +178,50 @@ private: |
| WorkerThreadCancelableTask* m_lastQueuedTask; |
| }; |
| -class WorkerThreadTask : public blink::WebThread::Task { |
| - WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED; |
| -public: |
| - static PassOwnPtr<WorkerThreadTask> create(WorkerThread& workerThread, PassOwnPtr<ExecutionContextTask> task, bool isInstrumented) |
| - { |
| - return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented)); |
| - } |
| +// WorkerThreadTask made private to WorkerThread |
| - virtual ~WorkerThreadTask() { } |
| +PassOwnPtr<WorkerThread::WorkerThreadTask> WorkerThread::WorkerThreadTask::create(WorkerThread& workerThread |
| + , PassOwnPtr<ExecutionContextTask> task, bool isInstrumented) |
| +{ |
| + return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented)); |
| +} |
| - virtual void run() OVERRIDE |
| - { |
| - WorkerGlobalScope* workerGlobalScope = m_workerThread.workerGlobalScope(); |
| - // Tasks could be put on the message loop after the cleanup task, |
| - // ensure none of those are ran. |
| - if (!workerGlobalScope) |
| - return; |
| +void WorkerThread::WorkerThreadTask::run() |
| +{ |
| + WorkerGlobalScope* workerGlobalScope = m_workerThread.workerGlobalScope(); |
| + // Tasks could be put on the message loop after the cleanup task, |
| + // ensure none of those are ran. |
| + if (!workerGlobalScope) |
| + return; |
| - if (m_isInstrumented) |
| - InspectorInstrumentation::willPerformExecutionContextTask(workerGlobalScope, m_task.get()); |
| - if ((!workerGlobalScope->isClosing() && !m_workerThread.terminated()) || m_task->isCleanupTask()) |
| + if (m_isInstrumented) |
| + InspectorInstrumentation::willPerformExecutionContextTask(workerGlobalScope, m_task.get()); |
| + if ((!workerGlobalScope->isClosing() && !m_workerThread.terminated()) || m_task->isCleanupTask()) |
| + if (!m_isIdleHandlerTask || (m_isIdleHandlerTask && !m_workerThread.taskCount())) { |
| m_task->performTask(workerGlobalScope); |
| - if (m_isInstrumented) |
| - InspectorInstrumentation::didPerformExecutionContextTask(workerGlobalScope); |
| - } |
| - |
| -private: |
| - WorkerThreadTask(WorkerThread& workerThread, PassOwnPtr<ExecutionContextTask> task, bool isInstrumented) |
| - : m_workerThread(workerThread) |
| - , m_task(task) |
| - , m_isInstrumented(isInstrumented) |
| - { |
| - if (m_isInstrumented) |
| - m_isInstrumented = !m_task->taskNameForInstrumentation().isEmpty(); |
| - if (m_isInstrumented) |
| - InspectorInstrumentation::didPostExecutionContextTask(m_workerThread.workerGlobalScope(), m_task.get()); |
| - } |
| + } |
| + if (m_isInstrumented) |
| + InspectorInstrumentation::didPerformExecutionContextTask(workerGlobalScope); |
| + |
| + // If no more tasks are queued up after this, then queue up the idleHandler |
| + // to trigger GC. |
| + if (!m_isIdleHandlerTask && !m_workerThread.decrementAndReturnTaskCount() |
| + && !m_workerThread.m_IdleHandlerTaskPosted) |
|
jochen (gone - plz use gerrit)
2014/10/14 13:46:03
nit. put on previous line
|
| + m_workerThread.queueUpIdleHandlerNow(kLongIdleHandlerDelayMs); |
| +} |
| - WorkerThread& m_workerThread; |
| - OwnPtr<ExecutionContextTask> m_task; |
| - bool m_isInstrumented; |
| -}; |
| +WorkerThread::WorkerThreadTask::WorkerThreadTask(WorkerThread& workerThread |
| + , PassOwnPtr<ExecutionContextTask> task, bool isInstrumented) |
| + : m_workerThread(workerThread) |
| + , m_task(task) |
| + , m_isInstrumented(isInstrumented) |
| + , m_isIdleHandlerTask(false) |
| +{ |
| + if (m_isInstrumented) |
| + m_isInstrumented = !m_task->taskNameForInstrumentation().isEmpty(); |
| + if (m_isInstrumented) |
| + InspectorInstrumentation::didPostExecutionContextTask(m_workerThread.workerGlobalScope(), m_task.get()); |
| +} |
| class RunDebuggerQueueTask FINAL : public ExecutionContextTask { |
| public: |
| @@ -246,6 +248,8 @@ WorkerThread::WorkerThread(WorkerLoaderProxy& workerLoaderProxy, WorkerReporting |
| , m_startupData(startupData) |
| , m_shutdownEvent(adoptPtr(blink::Platform::current()->createWaitableEvent())) |
| , m_terminationEvent(adoptPtr(blink::Platform::current()->createWaitableEvent())) |
| + , m_IdleHandlerTaskPosted(false) |
| + , m_tasksCount(0) |
| { |
| MutexLocker lock(threadSetMutex()); |
| workerThreads().add(this); |
| @@ -321,8 +325,6 @@ void WorkerThread::initialize() |
| script->evaluate(ScriptSourceCode(sourceCode, scriptURL)); |
| postInitialize(); |
| - |
| - postDelayedTask(createSameThreadTask(&WorkerThread::idleHandler, this), kShortIdleHandlerDelayMs); |
| } |
| void WorkerThread::cleanup() |
| @@ -459,29 +461,58 @@ bool WorkerThread::isCurrentThread() const |
| return m_thread && m_thread->isCurrentThread(); |
| } |
| +void WorkerThread::queueUpIdleHandlerNow(long long delayMs) |
| +{ |
| + 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.
|
| + createSameThreadTask(&WorkerThread::idleHandler, this), true); |
| + 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.
|
| + m_thread->postDelayedTask(idleHandlerTask.leakPtr(), delayMs); |
| + m_IdleHandlerTaskPosted = true; |
| +} |
| + |
| void WorkerThread::idleHandler() |
| { |
| ASSERT(m_workerGlobalScope.get()); |
| int64 delay = kLongIdleHandlerDelayMs; |
| + // Some tasks may have been started in the mean time, so lets return back |
| + // and wait for the next idleHandler to be fired. |
| + if (m_tasksCount) { |
| + 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.
|
| + return; |
| + } |
| // Do a script engine idle notification if the next event is distant enough. |
| const double kMinIdleTimespan = 0.3; |
| + // This is set to true when idleNotification returns false. |
| + // idleNotification returns false only when more GC is required. It returns |
| + // true if no more GC is required and that is when callGCAgain will be set to false. |
| + bool callGCAgain = false; |
| if (m_sharedTimer->nextFireTime() == 0.0 || m_sharedTimer->nextFireTime() > currentTime() + kMinIdleTimespan) { |
| - bool hasMoreWork = !m_workerGlobalScope->idleNotification(); |
| - if (hasMoreWork) |
| + callGCAgain = !m_workerGlobalScope->idleNotification(); |
| + if (callGCAgain) |
| delay = kShortIdleHandlerDelayMs; |
| } |
| + if (callGCAgain) |
| + queueUpIdleHandlerNow(delay); |
|
jochen (gone - plz use gerrit)
2014/10/14 13:46:03
should be 0
|
| + else |
| + 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.
|
| +} |
| - postDelayedTask(createSameThreadTask(&WorkerThread::idleHandler, this), delay); |
| +int WorkerThread::decrementAndReturnTaskCount() |
| +{ |
| + atomicDecrement(&m_tasksCount); |
| + return m_tasksCount; |
| } |
| void WorkerThread::postTask(PassOwnPtr<ExecutionContextTask> task) |
| { |
| + atomicIncrement(&m_tasksCount); |
| m_thread->postTask(WorkerThreadTask::create(*this, task, true).leakPtr()); |
| } |
| void WorkerThread::postDelayedTask(PassOwnPtr<ExecutionContextTask> task, long long delayMs) |
| { |
| + atomicIncrement(&m_tasksCount); |
| m_thread->postDelayedTask(WorkerThreadTask::create(*this, task, true).leakPtr(), delayMs); |
| } |