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); |
} |