Index: Source/platform/scheduler/Scheduler.cpp |
diff --git a/Source/platform/scheduler/Scheduler.cpp b/Source/platform/scheduler/Scheduler.cpp |
index c88c4203a6a7e3c9ad6a36fb3f400e6ea1a7bcc0..97d84e6ce45a7ef32dd0e2af96311d47796ea094 100644 |
--- a/Source/platform/scheduler/Scheduler.cpp |
+++ b/Source/platform/scheduler/Scheduler.cpp |
@@ -19,32 +19,6 @@ namespace { |
// The time we should stay in CompositorPriority mode for, after a touch event. |
double kLowSchedulerPolicyAfterTouchTimeSeconds = 0.1; |
-// Can be created from any thread. |
-// Note if the scheduler gets shutdown, this may be run after. |
-class MainThreadIdleTaskAdapter : public WebThread::Task { |
-public: |
- MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allottedTimeMs, const TraceLocation& location) |
- : m_idleTask(idleTask) |
- , m_allottedTimeMs(allottedTimeMs) |
- , m_location(location) |
- { |
- } |
- |
- // WebThread::Task implementation. |
- virtual void run() OVERRIDE |
- { |
- TRACE_EVENT2("blink", "MainThreadIdleTaskAdapter::run", |
- "src_file", m_location.fileName(), |
- "src_func", m_location.functionName()); |
- m_idleTask(m_allottedTimeMs); |
- } |
- |
-private: |
- Scheduler::IdleTask m_idleTask; |
- double m_allottedTimeMs; |
- TraceLocation m_location; |
-}; |
- |
} // namespace |
// Typically only created from compositor or render threads. |
@@ -86,16 +60,53 @@ public: |
virtual void run() OVERRIDE |
{ |
Scheduler* scheduler = Scheduler::shared(); |
- // FIXME: This check should't be necessary, tasks should not outlive blink. |
+ // FIXME: This check shouldn't be necessary, tasks should not outlive blink. |
ASSERT(scheduler); |
if (scheduler) |
- Scheduler::shared()->runPendingHighPriorityTasksIfInCompositorPriority(); |
+ scheduler->runPendingHighPriorityTasksIfInCompositorPriority(); |
+ |
m_task.run(); |
} |
- TracedTask m_task; |
+private: |
+ TracedStandardTask m_task; |
}; |
+ |
+// Can be created from any thread. |
+// Note if the scheduler gets shutdown, this may be run after. |
+class Scheduler::MainThreadPendingIdleTaskRunner : public WebThread::Task { |
+public: |
+ MainThreadPendingIdleTaskRunner(const TracedIdleTask& idleTask) |
+ : m_idleTask(idleTask) |
+ { |
+ ASSERT(Scheduler::shared()); |
+ } |
+ |
+ // WebThread::Task implementation. |
+ virtual void run() OVERRIDE |
+ { |
+ Scheduler* scheduler = Scheduler::shared(); |
+ // FIXME: This check shouldn't be necessary, tasks should not outlive blink. |
+ ASSERT(scheduler); |
+ if (scheduler) { |
+ scheduler->runPendingHighPriorityTasksIfInCompositorPriority(); |
+ |
+ if (scheduler->canRunIdleTask()) { |
+ m_idleTask.run(); |
+ // Run the next idle task if possible. |
+ scheduler->maybeExecuteIdleTask(); |
+ } else { |
+ scheduler->repostIdleTask(m_idleTask); |
+ } |
+ } |
+ } |
+ |
+private: |
+ TracedIdleTask m_idleTask; |
+}; |
+ |
+ |
Scheduler* Scheduler::s_sharedScheduler = nullptr; |
void Scheduler::initializeOnMainThread() |
@@ -118,6 +129,7 @@ Scheduler::Scheduler() |
: m_sharedTimerFunction(nullptr) |
, m_mainThread(blink::Platform::current()->currentThread()) |
, m_compositorPriorityPolicyEndTimeSeconds(0) |
+ , m_currentFrameDeadlineSeconds(0) |
, m_highPriorityTaskCount(0) |
, m_highPriorityTaskRunnerPosted(false) |
, m_schedulerPolicy(Normal) |
@@ -131,32 +143,36 @@ Scheduler::~Scheduler() |
} |
} |
-void Scheduler::willBeginFrame(const WebBeginFrameArgs& args) |
+void Scheduler::willBeginFrame(double frameDeadlineSeconds) |
{ |
- // TODO: Use frame deadline and interval to schedule idle tasks. |
-} |
+ m_currentFrameCommitted = false; |
+ m_currentFrameDeadlineSeconds = frameDeadlineSeconds; |
-void Scheduler::didCommitFrameToCompositor() |
-{ |
- // TODO: Trigger the frame deadline immediately. |
+ // TODO: Schedule a deferred task here to run idle work if didCommitFrameToCompositor never get's called |
} |
-void Scheduler::scheduleIdleTask(const TraceLocation& location, const IdleTask& idleTask) |
+void Scheduler::didCommitFrameToCompositor() |
{ |
- // TODO: send a real allottedTime here. |
- m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0, location)); |
+ m_currentFrameCommitted = true; |
+ maybeExecuteIdleTask(); |
} |
void Scheduler::postHighPriorityTaskInternal(const TraceLocation& location, const Task& task, const char* traceName) |
{ |
Locker<Mutex> lock(m_pendingTasksMutex); |
- m_pendingHighPriorityTasks.append(TracedTask(task, location, traceName)); |
+ m_pendingHighPriorityTasks.append(TracedStandardTask(task, location, traceName)); |
atomicIncrement(&m_highPriorityTaskCount); |
maybePostMainThreadPendingHighPriorityTaskRunner(); |
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPriorityTasks", m_highPriorityTaskCount); |
} |
+void Scheduler::postIdleTaskInternal(const TraceLocation& location, const IdleTask& idleTask, const char* traceName) |
+{ |
+ Locker<Mutex> lock(m_pendingTasksMutex); |
+ m_pendingIdleTasks.append(TracedIdleTask(idleTask, location, traceName)); |
+} |
+ |
void Scheduler::postTask(const TraceLocation& location, const Task& task) |
{ |
m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Scheduler::MainThreadTask")); |
@@ -184,6 +200,11 @@ void Scheduler::postIpcTask(const TraceLocation& location, const Task& task) |
m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Scheduler::IpcTask")); |
} |
+void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idleTask) |
+{ |
+ postIdleTaskInternal(location, idleTask, "Scheduler::IdleTask"); |
+} |
+ |
void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner() |
{ |
ASSERT(m_pendingTasksMutex.locked()); |
@@ -193,10 +214,6 @@ void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner() |
m_highPriorityTaskRunnerPosted = true; |
} |
-void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idleTask) |
-{ |
- scheduleIdleTask(location, idleTask); |
-} |
void Scheduler::tickSharedTimer() |
{ |
@@ -228,7 +245,7 @@ bool Scheduler::swapQueuesAndRunPendingTasks() |
// These locks guard against another thread posting input or compositor tasks while we swap the buffers. |
// One the buffers have been swapped we can safely access the returned deque without having to lock. |
m_pendingTasksMutex.lock(); |
- Deque<TracedTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers(); |
+ Deque<TracedStandardTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers(); |
maybeEnterNormalSchedulerPolicy(); |
m_pendingTasksMutex.unlock(); |
return executeHighPriorityTasks(highPriorityTasks); |
@@ -241,7 +258,7 @@ void Scheduler::swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPosting() |
// These locks guard against another thread posting input or compositor tasks while we swap the buffers. |
// One the buffers have been swapped we can safely access the returned deque without having to lock. |
m_pendingTasksMutex.lock(); |
- Deque<TracedTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers(); |
+ Deque<TracedStandardTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers(); |
m_highPriorityTaskRunnerPosted = false; |
maybeEnterNormalSchedulerPolicy(); |
m_pendingTasksMutex.unlock(); |
@@ -258,7 +275,7 @@ void Scheduler::maybeEnterNormalSchedulerPolicy() |
enterSchedulerPolicyLocked(Normal); |
} |
-bool Scheduler::executeHighPriorityTasks(Deque<TracedTask>& highPriorityTasks) |
+bool Scheduler::executeHighPriorityTasks(Deque<TracedStandardTask>& highPriorityTasks) |
{ |
TRACE_EVENT0("blink", "Scheduler::executeHighPriorityTasks"); |
int highPriorityTasksExecuted = 0; |
@@ -273,6 +290,26 @@ bool Scheduler::executeHighPriorityTasks(Deque<TracedTask>& highPriorityTasks) |
return highPriorityTasksExecuted > 0; |
} |
+bool Scheduler::maybeExecuteIdleTask() |
+{ |
+ TRACE_EVENT0("blink", "Scheduler::maybeExecuteIdleTask"); |
+ if (canRunIdleTask()) { |
+ Locker<Mutex> lock(m_pendingTasksMutex); |
+ if (!m_pendingIdleTasks.isEmpty()) { |
+ m_mainThread->postTask(new MainThreadPendingIdleTaskRunner(m_pendingIdleTasks.takeFirst())); |
+ return true; |
+ } |
+ } |
picksi1
2014/09/30 09:13:51
Is this function correctly named? It isn't actuall
rmcilroy
2014/09/30 09:56:19
Yes it's tricky to name - I originally had maybeSc
picksi1
2014/09/30 12:34:00
maybePostMainThreadPendingHighPriorityTaskRunner()
|
+ return false; |
+} |
+ |
+void Scheduler::repostIdleTask(const TracedIdleTask& idleTask) |
+{ |
+ Locker<Mutex> lock(m_pendingTasksMutex); |
+ // Post at the front since the task didn't get a chance to run. |
+ m_pendingIdleTasks.prepend(idleTask); |
+} |
+ |
picksi1
2014/09/30 09:13:51
Should this be called repostAtFront (etc) or somet
rmcilroy
2014/09/30 09:56:19
Done.
|
void Scheduler::sharedTimerAdapter() |
{ |
shared()->tickSharedTimer(); |
@@ -313,6 +350,16 @@ bool Scheduler::hasPendingHighPriorityWork() const |
return acquireLoad(&m_highPriorityTaskCount) != 0; |
} |
+double Scheduler::currentFrameDeadlineSeconds() const |
+{ |
+ return m_currentFrameDeadlineSeconds; |
+} |
+ |
+bool Scheduler::canRunIdleTask() const |
+{ |
+ return m_currentFrameCommitted && (m_currentFrameDeadlineSeconds > Platform::current()->monotonicallyIncreasingTime()); |
+} |
+ |
Scheduler::SchedulerPolicy Scheduler::schedulerPolicy() const |
{ |
ASSERT(isMainThread()); |