Index: cc/test/ordered_simple_task_runner.cc |
diff --git a/cc/test/ordered_simple_task_runner.cc b/cc/test/ordered_simple_task_runner.cc |
index 188ffe72b5f8adea6208635d68263b3139811000..de7223efb9e61d6afb220ab15d6f2d9cd4208db5 100644 |
--- a/cc/test/ordered_simple_task_runner.cc |
+++ b/cc/test/ordered_simple_task_runner.cc |
@@ -6,8 +6,18 @@ |
#include <algorithm> |
#include <deque> |
+#include <sstream> |
+#include <string> |
-#include "base/logging.h" |
+#include "base/debug/trace_event.h" |
+#include "base/debug/trace_event_argument.h" |
+#include "base/strings/string_number_conversions.h" |
+ |
+#define TRACE_TASK(function, task) \ |
+ TRACE_EVENT_INSTANT1( \ |
+ "cc", function, TRACE_EVENT_SCOPE_THREAD, "task", TaskAsValue(task)); |
+ |
+#define TRACE_TASK_RUN(function, tag, task) |
namespace { |
@@ -16,26 +26,166 @@ bool TestPendingTaskComparator(const base::TestPendingTask& lhs, |
return lhs.ShouldRunBefore(rhs); |
} |
+void TaskAsValueInto(const base::TestPendingTask& task, |
+ base::debug::TracedValue* state) { |
+ state->SetInteger("run_at", task.GetTimeToRun().ToInternalValue()); |
+ state->SetString("posted_from", task.location.ToString()); |
} |
+scoped_refptr<base::debug::ConvertableToTraceFormat> TaskAsValue( |
+ const base::TestPendingTask& task) { |
+ scoped_refptr<base::debug::TracedValue> state = |
+ new base::debug::TracedValue(); |
+ TaskAsValueInto(task, state); |
+ return state; |
+} |
+ |
+} // namespace |
+ |
namespace cc { |
-OrderedSimpleTaskRunner::OrderedSimpleTaskRunner() {} |
+void OrderedSimpleTaskRunner::SortTasks( |
+ std::deque<base::TestPendingTask>* tasks) { |
+ std::stable_sort(tasks->begin(), tasks->end(), TestPendingTaskComparator); |
+} |
+ |
+OrderedSimpleTaskRunner::OrderedSimpleTaskRunner() |
+ : advance_now_(true), |
+ now_src_(TestNowSource::Create()), |
+ inside_run_pending_tasks_(false) { |
+} |
+ |
+OrderedSimpleTaskRunner::OrderedSimpleTaskRunner( |
+ scoped_refptr<TestNowSource> now_src, |
+ bool advance_now) |
+ : advance_now_(advance_now), |
+ now_src_(now_src), |
+ inside_run_pending_tasks_(false) { |
+} |
OrderedSimpleTaskRunner::~OrderedSimpleTaskRunner() {} |
+// base::TestSimpleTaskRunner implementation |
+bool OrderedSimpleTaskRunner::PostDelayedTask( |
+ const tracked_objects::Location& from_here, |
+ const base::Closure& task, |
+ base::TimeDelta delay) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ base::TestPendingTask pt( |
+ from_here, task, now_src_->Now(), delay, base::TestPendingTask::NESTABLE); |
+ |
+ TRACE_TASK("OrderedSimpleTaskRunner::PostDelayedTask", pt); |
+ |
+ pending_tasks_.push_back(pt); |
+ SortTasks(&pending_tasks_); |
+ return true; |
+} |
+ |
+bool OrderedSimpleTaskRunner::PostNonNestableDelayedTask( |
+ const tracked_objects::Location& from_here, |
+ const base::Closure& task, |
+ base::TimeDelta delay) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ base::TestPendingTask pt(from_here, |
+ task, |
+ now_src_->Now(), |
+ delay, |
+ base::TestPendingTask::NON_NESTABLE); |
+ |
+ TRACE_TASK("OrderedSimpleTaskRunner::PostNonNestableDelayedTask", pt); |
+ |
+ pending_tasks_.push_back(pt); |
+ SortTasks(&pending_tasks_); |
+ return true; |
+} |
+ |
void OrderedSimpleTaskRunner::RunPendingTasks() { |
+ TRACE_EVENT1( |
+ "cc", "OrderedSimpleTaskRunner::RunPendingTasks", "this", AsValue()); |
DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ if (inside_run_pending_tasks_) |
+ return; |
+ inside_run_pending_tasks_ = true; |
+ |
// Swap with a local variable to avoid re-entrancy problems. |
std::deque<base::TestPendingTask> tasks_to_run; |
tasks_to_run.swap(pending_tasks_); |
- std::stable_sort(tasks_to_run.begin(), |
- tasks_to_run.end(), |
- TestPendingTaskComparator); |
- for (std::deque<base::TestPendingTask>::iterator it = tasks_to_run.begin(); |
- it != tasks_to_run.end(); ++it) { |
- it->task.Run(); |
+ |
+ std::deque<base::TestPendingTask>::iterator it = tasks_to_run.begin(); |
+ for (; it != tasks_to_run.end(); ++it) { |
+ base::TimeTicks task_time = it->GetTimeToRun(); |
+ |
+ // Have new items been added to pending_tasks which need to run before this |
+ // task? |
+ if (pending_tasks_.size() > 0 && |
+ task_time > pending_tasks_.begin()->GetTimeToRun()) { |
+ break; |
+ } |
+ |
+ // Is the task in the future? |
+ if (task_time > now_src_->Now()) { |
+ if (!advance_now_) |
+ break; |
+ else |
+ now_src_->SetNow(task_time); |
+ } |
+ |
+ { |
+ TRACE_EVENT1("cc", |
+ "OrderedSimpleTaskRunner::RunPendingTasks running", |
+ "task", |
+ TaskAsValue(*it)); |
+ it->task.Run(); |
+ } |
+ } |
+ |
+ // Push any remaining tasks back into the pending queue |
+ for (; it != tasks_to_run.end(); ++it) { |
+ pending_tasks_.push_front(*it); |
+ } |
+ SortTasks(&pending_tasks_); |
+ |
+ inside_run_pending_tasks_ = false; |
+} |
+ |
+base::TimeDelta OrderedSimpleTaskRunner::DelayToNextPendingTask() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ base::TimeDelta delay = |
+ pending_tasks_.front().GetTimeToRun() - now_src_->Now(); |
+ if (delay > base::TimeDelta()) |
+ return delay; |
+ return base::TimeDelta(); |
+} |
+ |
+void OrderedSimpleTaskRunner::SetAutoAdvanceNowToPendingTasks( |
+ bool advance_now) { |
+ advance_now_ = advance_now; |
+} |
+ |
+// base::debug tracing functionality |
+scoped_refptr<base::debug::ConvertableToTraceFormat> |
+OrderedSimpleTaskRunner::AsValue() const { |
+ scoped_refptr<base::debug::TracedValue> state = |
+ new base::debug::TracedValue(); |
+ AsValueInto(state); |
+ return state; |
+} |
+ |
+void OrderedSimpleTaskRunner::AsValueInto( |
+ base::debug::TracedValue* state) const { |
+ state->SetInteger("pending_tasks", pending_tasks_.size()); |
+ for (std::deque<base::TestPendingTask>::const_iterator it = |
+ pending_tasks_.begin(); |
+ it != pending_tasks_.end(); |
+ ++it) { |
+ state->BeginDictionary( |
+ base::SizeTToString(std::distance(pending_tasks_.begin(), it)).c_str()); |
+ TaskAsValueInto(*it, state); |
+ state->EndDictionary(); |
} |
+ now_src_->AsValueInto(state); |
} |
} // namespace cc |