Index: Source/platform/scheduler/Scheduler.cpp |
diff --git a/Source/platform/scheduler/Scheduler.cpp b/Source/platform/scheduler/Scheduler.cpp |
index e33f7132488807395ca7af8032e2fadf79e8709c..839d911983d63a5ba898a1c2c3abcaeeb5f55a4f 100644 |
--- a/Source/platform/scheduler/Scheduler.cpp |
+++ b/Source/platform/scheduler/Scheduler.cpp |
@@ -20,41 +20,40 @@ namespace { |
// The time we should stay in CompositorPriority mode for, after a touch event. |
double kLowSchedulerPolicyAfterTouchTimeSeconds = 0.1; |
-// Can be created from any thread. |
+} // namespace |
+ |
+// Typically only created from compositor or render threads. |
// Note if the scheduler gets shutdown, this may be run after. |
-class MainThreadIdleTaskAdapter : public WebThread::Task { |
+class Scheduler::MainThreadPendingHighPriorityTaskRunner : public WebThread::Task { |
public: |
- MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allottedTimeMs, const TraceLocation& location) |
- : m_idleTask(idleTask) |
- , m_allottedTimeMs(allottedTimeMs) |
- , m_location(location) |
+ MainThreadPendingHighPriorityTaskRunner( |
+ const Scheduler::Task& task, const TraceLocation& location, const char* traceName) |
+ : m_task(internal::TracedStandardTask::Create(task, location, traceName)) |
{ |
+ ASSERT(Scheduler::shared()); |
} |
// 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); |
+ m_task->run(); |
+ if (Scheduler* scheduler = Scheduler::shared()) { |
+ scheduler->updatePolicy(); |
+ scheduler->didRunHighPriorityTask(); |
+ } |
} |
private: |
- Scheduler::IdleTask m_idleTask; |
- double m_allottedTimeMs; |
- TraceLocation m_location; |
+ OwnPtr<internal::TracedStandardTask> m_task; |
}; |
-} // namespace |
- |
-// Typically only created from compositor or render threads. |
+// Can be created from any thread. |
// Note if the scheduler gets shutdown, this may be run after. |
-class Scheduler::MainThreadPendingHighPriorityTaskRunner : public WebThread::Task { |
+class Scheduler::MainThreadPendingTaskRunner : public WebThread::Task { |
public: |
- MainThreadPendingHighPriorityTaskRunner( |
+ MainThreadPendingTaskRunner( |
const Scheduler::Task& task, const TraceLocation& location, const char* traceName) |
- : m_task(task, location, traceName) |
+ : m_task(internal::TracedStandardTask::Create(task, location, traceName)) |
{ |
ASSERT(Scheduler::shared()); |
} |
@@ -62,24 +61,22 @@ public: |
// WebThread::Task implementation. |
virtual void run() OVERRIDE |
{ |
- m_task.run(); |
+ m_task->run(); |
if (Scheduler* scheduler = Scheduler::shared()) { |
scheduler->updatePolicy(); |
- scheduler->didRunHighPriorityTask(); |
} |
} |
private: |
- TracedTask m_task; |
+ OwnPtr<internal::TracedStandardTask> m_task; |
}; |
+ |
// Can be created from any thread. |
// Note if the scheduler gets shutdown, this may be run after. |
-class Scheduler::MainThreadPendingTaskRunner : public WebThread::Task { |
+class Scheduler::MainThreadPendingIdleTaskRunner : public WebThread::Task { |
public: |
- MainThreadPendingTaskRunner( |
- const Scheduler::Task& task, const TraceLocation& location, const char* traceName) |
- : m_task(task, location, traceName) |
+ MainThreadPendingIdleTaskRunner() |
{ |
ASSERT(Scheduler::shared()); |
} |
@@ -87,15 +84,19 @@ public: |
// WebThread::Task implementation. |
virtual void run() OVERRIDE |
{ |
- m_task.run(); |
- if (Scheduler* scheduler = Scheduler::shared()) { |
- scheduler->updatePolicy(); |
+ Scheduler* scheduler = Scheduler::shared(); |
+ // FIXME: This check shouldn't be necessary, tasks should not outlive blink. |
Sami
2014/10/07 14:17:34
I don't think this comment is accurate any longer.
rmcilroy
2014/10/07 15:37:51
Done.
|
+ ASSERT(scheduler); |
+ if (scheduler) { |
+ scheduler->maybeRunPendingIdleTask(); |
+ // If possible, run the next idle task by reposting on the main thread. |
+ scheduler->maybePostMainThreadPendingIdleTask(); |
} |
} |
- TracedTask m_task; |
}; |
+ |
Scheduler* Scheduler::s_sharedScheduler = nullptr; |
void Scheduler::initializeOnMainThread() |
@@ -117,6 +118,7 @@ Scheduler* Scheduler::shared() |
Scheduler::Scheduler() |
: m_sharedTimerFunction(nullptr) |
, m_mainThread(blink::Platform::current()->currentThread()) |
+ , m_estimatedNextBeginFrameSeconds(0) |
, m_highPriorityTaskCount(0) |
, m_highPriorityTaskRunnerPosted(false) |
, m_compositorPriorityPolicyEndTimeSeconds(0) |
@@ -128,20 +130,19 @@ Scheduler::~Scheduler() |
{ |
} |
-void Scheduler::willBeginFrame(const WebBeginFrameArgs& args) |
+void Scheduler::willBeginFrame(double estimatedNextBeginFrameSeconds) |
{ |
- // TODO: Use frame deadline and interval to schedule idle tasks. |
+ ASSERT(isMainThread()); |
+ m_currentFrameCommitted = false; |
+ m_estimatedNextBeginFrameSeconds = estimatedNextBeginFrameSeconds; |
+ // TODO: Schedule a deferred task here to run idle work if didCommitFrameToCompositor never gets called. |
} |
void Scheduler::didCommitFrameToCompositor() |
{ |
- // TODO: Trigger the frame deadline immediately. |
-} |
- |
-void Scheduler::scheduleIdleTask(const TraceLocation& location, const IdleTask& idleTask) |
-{ |
- // TODO: send a real allottedTime here. |
- m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0, location)); |
+ ASSERT(isMainThread()); |
+ m_currentFrameCommitted = true; |
+ maybePostMainThreadPendingIdleTask(); |
} |
void Scheduler::postHighPriorityTaskInternal(const TraceLocation& location, const Task& task, const char* traceName) |
@@ -157,6 +158,12 @@ void Scheduler::didRunHighPriorityTask() |
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_pendingIdleTasksMutex); |
+ m_pendingIdleTasks.append(internal::TracedIdleTask::Create(idleTask, location, traceName)); |
+} |
+ |
void Scheduler::postTask(const TraceLocation& location, const Task& task) |
{ |
m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Scheduler::MainThreadTask")); |
@@ -188,7 +195,21 @@ void Scheduler::postIpcTask(const TraceLocation& location, const Task& task) |
void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idleTask) |
{ |
- scheduleIdleTask(location, idleTask); |
+ postIdleTaskInternal(location, idleTask, "Scheduler::IdleTask"); |
+} |
+ |
+bool Scheduler::maybePostMainThreadPendingIdleTask() |
+{ |
+ ASSERT(isMainThread()); |
+ TRACE_EVENT0("blink", "Scheduler::maybePostMainThreadPendingIdleTask"); |
+ if (canRunIdleTask()) { |
+ Locker<Mutex> lock(m_pendingIdleTasksMutex); |
+ if (!m_pendingIdleTasks.isEmpty()) { |
+ m_mainThread->postTask(new MainThreadPendingIdleTaskRunner()); |
+ return true; |
+ } |
+ } |
+ return false; |
} |
void Scheduler::tickSharedTimer() |
@@ -242,6 +263,38 @@ bool Scheduler::shouldYieldForHighPriorityWork() const |
return acquireLoad(&m_highPriorityTaskCount) != 0; |
} |
+bool Scheduler::maybeRunPendingIdleTask() |
+{ |
+ ASSERT(isMainThread()); |
+ if (!canRunIdleTask()) |
+ return false; |
+ |
+ takeFirstPendingIdleTask()->run(); |
+ return true; |
+} |
+ |
+PassOwnPtr<internal::TracedIdleTask> Scheduler::takeFirstPendingIdleTask() |
+{ |
+ Locker<Mutex> lock(m_pendingIdleTasksMutex); |
+ ASSERT(!m_pendingIdleTasks.isEmpty()); |
+ return m_pendingIdleTasks.takeFirst(); |
+} |
+ |
+double Scheduler::currentFrameDeadlineForIdleTasks() const |
+{ |
+ ASSERT(isMainThread()); |
+ // TODO: Make idle time more fine-grain chunks when in Compositor priority. |
+ return m_estimatedNextBeginFrameSeconds; |
+} |
+ |
+bool Scheduler::canRunIdleTask() const |
+{ |
+ ASSERT(isMainThread()); |
+ return m_currentFrameCommitted |
+ && !shouldYieldForHighPriorityWork() |
+ && (m_estimatedNextBeginFrameSeconds > Platform::current()->monotonicallyIncreasingTime()); |
+} |
+ |
Scheduler::SchedulerPolicy Scheduler::schedulerPolicy() const |
{ |
ASSERT(isMainThread()); |