Index: Source/core/workers/WorkerThread.cpp |
diff --git a/Source/core/workers/WorkerThread.cpp b/Source/core/workers/WorkerThread.cpp |
index 988256e367b9a256b1245ff2fdac409fb9aa786d..e5fe43132ef59d5e9d4b651d10fbe30a46698b6e 100644 |
--- a/Source/core/workers/WorkerThread.cpp |
+++ b/Source/core/workers/WorkerThread.cpp |
@@ -85,6 +85,74 @@ unsigned WorkerThread::workerThreadCount() |
return workerThreads().size(); |
} |
+class WorkerThreadTask : public blink::WebThread::Task { |
jochen (gone - plz use gerrit)
2014/09/15 14:29:41
why do you move this class up here?
Mayur Kankanwadi
2014/09/15 14:38:27
Was done to fix earlier compilation errors. Fixed
|
+ WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED; |
+public: |
+ static PassOwnPtr<WorkerThreadTask> create(const WorkerThread& workerThread, PassOwnPtr<ExecutionContextTask> task, bool isInstrumented) |
+ { |
+ return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented)); |
+ } |
+ |
+ virtual ~WorkerThreadTask() { } |
+ |
+ 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; |
+ |
+ if (m_isInstrumented) |
+ InspectorInstrumentation::willPerformExecutionContextTask(workerGlobalScope, m_task.get()); |
+ if ((!workerGlobalScope->isClosing() && !m_workerThread.terminated()) || m_task->isCleanupTask()) |
+ m_task->performTask(workerGlobalScope); |
+ if (m_isInstrumented) |
+ InspectorInstrumentation::didPerformExecutionContextTask(workerGlobalScope); |
+ } |
+ |
+private: |
+ WorkerThreadTask(const 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()); |
+ } |
+ |
+ const WorkerThread& m_workerThread; |
+ OwnPtr<ExecutionContextTask> m_task; |
+ bool m_isInstrumented; |
+}; |
+ |
+class WorkerThreadCancelableTask FINAL : public ExecutionContextTask { |
jochen (gone - plz use gerrit)
2014/09/15 14:29:42
add wtf_make_noncopyable and fast allocated macros
Mayur Kankanwadi
2014/09/15 14:38:27
Done.
|
+public: |
+ static PassOwnPtr<WorkerThreadCancelableTask> create(const Closure& closure) |
+ { |
+ return adoptPtr(new WorkerThreadCancelableTask(closure)); |
+ } |
+ |
+ virtual void performTask(ExecutionContext*) OVERRIDE |
+ { |
+ if (!m_taskCanceled) |
+ m_closure(); |
+ } |
+ |
+ void cancelTask() { m_taskCanceled = true; } |
+ |
+private: |
+ explicit WorkerThreadCancelableTask(const Closure& closure) |
+ : m_closure(closure) |
+ , m_taskCanceled(false) |
+ { } |
+ |
+ Closure m_closure; |
+ bool m_taskCanceled; |
+}; |
+ |
class WorkerSharedTimer : public SharedTimer { |
public: |
explicit WorkerSharedTimer(WorkerThread* workerThread) |
@@ -116,12 +184,28 @@ public: |
m_running = true; |
m_nextFireTime = currentTime() + interval; |
- m_workerThread->postDelayedTask(createSameThreadTask(&WorkerSharedTimer::OnTimeout, this), delay); |
+ if (m_lastQueuedTask) { |
+ // If something was queued up before this, check if its later than the current timer |
+ if (interval < m_lastQueuedTaskTimer->nextFireInterval()) { |
+ m_lastQueuedTask->cancelTask(); |
+ m_lastQueuedTask = 0; |
+ m_lastQueuedTaskTimer = 0; |
+ } |
+ } |
+ if (!m_lastQueuedTask) { |
+ // Now queue the task as a cancellable one. |
+ m_lastQueuedTask = WorkerThreadCancelableTask::create(bind(&WorkerSharedTimer::OnTimeout, this)).leakPtr(); |
+ m_workerThread->postDelayedTask(adoptPtr(m_lastQueuedTask), delay); |
+ // The current timer should ideally be at the top of the heap as its assumed to be the smallest interval in the heap |
+ m_lastQueuedTaskTimer = PlatformThreadData::current().threadTimers().timerHeap().first(); |
+ } |
} |
virtual void stop() |
{ |
m_running = false; |
+ m_lastQueuedTask = 0; |
+ m_lastQueuedTaskTimer = 0; |
} |
double nextFireTime() { return m_nextFireTime; } |
@@ -130,6 +214,10 @@ private: |
void OnTimeout() |
{ |
ASSERT(m_workerThread->workerGlobalScope()); |
+ |
+ m_lastQueuedTask = 0; |
+ m_lastQueuedTaskTimer = 0; |
+ |
if (m_sharedTimerFunction && m_running && !m_workerThread->workerGlobalScope()->isClosing()) |
m_sharedTimerFunction(); |
} |
@@ -138,50 +226,12 @@ private: |
SharedTimerFunction m_sharedTimerFunction; |
double m_nextFireTime; |
bool m_running; |
+ static WorkerThreadCancelableTask* m_lastQueuedTask; |
jochen (gone - plz use gerrit)
2014/09/15 14:29:42
why static? there can be several worker threads
Mayur Kankanwadi
2014/09/15 14:38:27
Yes, it's unnecessary.
Acknowledged.
|
+ static TimerBase* m_lastQueuedTaskTimer; |
}; |
-class WorkerThreadTask : public blink::WebThread::Task { |
- WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED; |
-public: |
- static PassOwnPtr<WorkerThreadTask> create(const WorkerThread& workerThread, PassOwnPtr<ExecutionContextTask> task, bool isInstrumented) |
- { |
- return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented)); |
- } |
- |
- virtual ~WorkerThreadTask() { } |
- |
- 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; |
- |
- if (m_isInstrumented) |
- InspectorInstrumentation::willPerformExecutionContextTask(workerGlobalScope, m_task.get()); |
- if ((!workerGlobalScope->isClosing() && !m_workerThread.terminated()) || m_task->isCleanupTask()) |
- m_task->performTask(workerGlobalScope); |
- if (m_isInstrumented) |
- InspectorInstrumentation::didPerformExecutionContextTask(workerGlobalScope); |
- } |
- |
-private: |
- WorkerThreadTask(const 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()); |
- } |
- |
- const WorkerThread& m_workerThread; |
- OwnPtr<ExecutionContextTask> m_task; |
- bool m_isInstrumented; |
-}; |
+WorkerThreadCancelableTask* WorkerSharedTimer::m_lastQueuedTask = 0; |
+TimerBase* WorkerSharedTimer::m_lastQueuedTaskTimer = 0; |
class RunDebuggerQueueTask FINAL : public ExecutionContextTask { |
public: |