| Index: Source/core/workers/WorkerThread.cpp
|
| diff --git a/Source/core/workers/WorkerThread.cpp b/Source/core/workers/WorkerThread.cpp
|
| index 6b444d379c3e6da148216e69ff8901912ea97fad..5eb9bf12b926c235fc0e4832c81676c09a1d2ae0 100644
|
| --- a/Source/core/workers/WorkerThread.cpp
|
| +++ b/Source/core/workers/WorkerThread.cpp
|
| @@ -85,12 +85,40 @@ unsigned WorkerThread::workerThreadCount()
|
| return workerThreads().size();
|
| }
|
|
|
| +class WorkerThreadCancelableTask FINAL : public ExecutionContextTask {
|
| + WTF_MAKE_NONCOPYABLE(WorkerThreadCancelableTask); WTF_MAKE_FAST_ALLOCATED;
|
| +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)
|
| : m_workerThread(workerThread)
|
| , m_nextFireTime(0.0)
|
| , m_running(false)
|
| + , m_lastQueuedTask(0)
|
| + , m_lastQueuedTaskTimer(0)
|
| { }
|
|
|
| typedef void (*SharedTimerFunction)();
|
| @@ -116,12 +144,33 @@ 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 (m_lastQueuedTaskTimer->isActive()) {
|
| + if (interval < m_lastQueuedTaskTimer->nextFireInterval()) {
|
| + m_lastQueuedTask->cancelTask();
|
| + m_lastQueuedTask = 0;
|
| + m_lastQueuedTaskTimer = 0;
|
| + }
|
| + } else {
|
| + 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 +179,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,6 +191,8 @@ private:
|
| SharedTimerFunction m_sharedTimerFunction;
|
| double m_nextFireTime;
|
| bool m_running;
|
| + WorkerThreadCancelableTask* m_lastQueuedTask;
|
| + TimerBase* m_lastQueuedTaskTimer;
|
| };
|
|
|
| class WorkerThreadTask : public blink::WebThread::Task {
|
|
|