Index: components/scheduler/child/task_queue_manager.cc |
diff --git a/components/scheduler/child/task_queue_manager.cc b/components/scheduler/child/task_queue_manager.cc |
index 620ede55ed35563d6e4c42a9f11fabf2d8e483ae..606fe7f35b0bcb5c41459f179057f7d0578a900d 100644 |
--- a/components/scheduler/child/task_queue_manager.cc |
+++ b/components/scheduler/child/task_queue_manager.cc |
@@ -12,6 +12,7 @@ |
#include "base/trace_event/trace_event.h" |
#include "base/trace_event/trace_event_argument.h" |
#include "components/scheduler/child/nestable_single_thread_task_runner.h" |
+#include "components/scheduler/child/task_queue.h" |
#include "components/scheduler/child/task_queue_selector.h" |
namespace { |
@@ -44,13 +45,13 @@ class LazyNow { |
base::TimeTicks now_; |
}; |
-class TaskQueue : public base::SingleThreadTaskRunner { |
+class TaskQueueImpl : public TaskQueue { |
public: |
- TaskQueue(TaskQueueManager* task_queue_manager, |
- const char* disabled_by_default_tracing_category, |
- const char* disabled_by_default_verbose_tracing_category); |
+ TaskQueueImpl(TaskQueueManager* task_queue_manager, |
+ const char* disabled_by_default_tracing_category, |
+ const char* disabled_by_default_verbose_tracing_category); |
- // base::SingleThreadTaskRunner implementation. |
+ // TaskQueue :implementation. |
bool RunsTasksOnCurrentThread() const override; |
bool PostDelayedTask(const tracked_objects::Location& from_here, |
const base::Closure& task, |
@@ -63,6 +64,9 @@ class TaskQueue : public base::SingleThreadTaskRunner { |
base::TimeDelta delay) override { |
return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE); |
} |
+ bool PostDelayedTaskAt(const tracked_objects::Location& from_here, |
+ const base::Closure& task, |
+ base::TimeTicks desired_run_time) override; |
TaskQueueManager::QueueState GetQueueState() const; |
@@ -101,12 +105,17 @@ class TaskQueue : public base::SingleThreadTaskRunner { |
NON_NESTABLE, |
}; |
- ~TaskQueue() override; |
+ ~TaskQueueImpl() override; |
bool PostDelayedTaskImpl(const tracked_objects::Location& from_here, |
const base::Closure& task, |
base::TimeDelta delay, |
TaskType task_type); |
+ bool PostDelayedTaskLocked(LazyNow* lazy_now, |
+ const tracked_objects::Location& from_here, |
+ const base::Closure& task, |
+ base::TimeTicks desired_run_time, |
+ TaskType task_type); |
// Delayed task posted to the underlying run loop, which locks |lock_| and |
// calls MoveReadyDelayedTasksToIncomingQueueLocked to process dealyed tasks |
@@ -149,6 +158,11 @@ class TaskQueue : public base::SingleThreadTaskRunner { |
const char* name_; |
const char* disabled_by_default_tracing_category_; |
const char* disabled_by_default_verbose_tracing_category_; |
+ |
+ // Queue-local task sequence number for maintaining the order of delayed |
+ // tasks which are posted for the exact same time. Note that this will be |
+ // replaced by the global sequence number when the delay has elapsed. |
+ int delayed_task_sequence_number_; |
base::DelayedTaskQueue delayed_task_queue_; |
std::set<base::TimeTicks> in_flight_kick_delayed_tasks_; |
@@ -156,12 +170,13 @@ class TaskQueue : public base::SingleThreadTaskRunner { |
base::TaskQueue work_queue_; |
TaskQueueManager::WakeupPolicy wakeup_policy_; |
- DISALLOW_COPY_AND_ASSIGN(TaskQueue); |
+ DISALLOW_COPY_AND_ASSIGN(TaskQueueImpl); |
}; |
-TaskQueue::TaskQueue(TaskQueueManager* task_queue_manager, |
- const char* disabled_by_default_tracing_category, |
- const char* disabled_by_default_verbose_tracing_category) |
+TaskQueueImpl::TaskQueueImpl( |
+ TaskQueueManager* task_queue_manager, |
+ const char* disabled_by_default_tracing_category, |
+ const char* disabled_by_default_verbose_tracing_category) |
: thread_id_(base::PlatformThread::CurrentId()), |
task_queue_manager_(task_queue_manager), |
pump_policy_(TaskQueueManager::PumpPolicy::AUTO), |
@@ -170,13 +185,12 @@ TaskQueue::TaskQueue(TaskQueueManager* task_queue_manager, |
disabled_by_default_tracing_category), |
disabled_by_default_verbose_tracing_category_( |
disabled_by_default_verbose_tracing_category), |
- wakeup_policy_(TaskQueueManager::WakeupPolicy::CAN_WAKE_OTHER_QUEUES) { |
-} |
+ delayed_task_sequence_number_(0), |
+ wakeup_policy_(TaskQueueManager::WakeupPolicy::CAN_WAKE_OTHER_QUEUES) {} |
-TaskQueue::~TaskQueue() { |
-} |
+TaskQueueImpl::~TaskQueueImpl() {} |
-void TaskQueue::WillDeleteTaskQueueManager() { |
+void TaskQueueImpl::WillDeleteTaskQueueManager() { |
base::AutoLock lock(lock_); |
task_queue_manager_ = nullptr; |
delayed_task_queue_ = base::DelayedTaskQueue(); |
@@ -184,40 +198,67 @@ void TaskQueue::WillDeleteTaskQueueManager() { |
work_queue_ = base::TaskQueue(); |
} |
-bool TaskQueue::RunsTasksOnCurrentThread() const { |
+bool TaskQueueImpl::RunsTasksOnCurrentThread() const { |
base::AutoLock lock(lock_); |
return base::PlatformThread::CurrentId() == thread_id_; |
} |
-bool TaskQueue::PostDelayedTaskImpl(const tracked_objects::Location& from_here, |
- const base::Closure& task, |
- base::TimeDelta delay, |
- TaskType task_type) { |
+bool TaskQueueImpl::PostDelayedTaskAt( |
+ const tracked_objects::Location& from_here, |
+ const base::Closure& task, |
+ base::TimeTicks desired_run_time) { |
+ base::AutoLock lock(lock_); |
+ if (!task_queue_manager_) |
+ return false; |
+ LazyNow lazy_now(task_queue_manager_); |
+ return PostDelayedTaskLocked(&lazy_now, from_here, task, desired_run_time, |
+ TaskType::NORMAL); |
+} |
+ |
+bool TaskQueueImpl::PostDelayedTaskImpl( |
+ const tracked_objects::Location& from_here, |
+ const base::Closure& task, |
+ base::TimeDelta delay, |
+ TaskType task_type) { |
base::AutoLock lock(lock_); |
if (!task_queue_manager_) |
return false; |
+ LazyNow lazy_now(task_queue_manager_); |
+ base::TimeTicks desired_run_time; |
+ if (delay > base::TimeDelta()) |
+ desired_run_time = lazy_now.Now() + delay; |
+ return PostDelayedTaskLocked(&lazy_now, from_here, task, desired_run_time, |
+ task_type); |
+} |
+ |
+bool TaskQueueImpl::PostDelayedTaskLocked( |
+ LazyNow* lazy_now, |
+ const tracked_objects::Location& from_here, |
+ const base::Closure& task, |
+ base::TimeTicks desired_run_time, |
+ TaskType task_type) { |
+ lock_.AssertAcquired(); |
+ DCHECK(task_queue_manager_); |
base::PendingTask pending_task(from_here, task, base::TimeTicks(), |
task_type != TaskType::NON_NESTABLE); |
task_queue_manager_->DidQueueTask(pending_task); |
- if (delay > base::TimeDelta()) { |
- base::TimeTicks now = task_queue_manager_->Now(); |
- pending_task.delayed_run_time = now + delay; |
+ if (!desired_run_time.is_null()) { |
+ pending_task.delayed_run_time = std::max(lazy_now->Now(), desired_run_time); |
+ pending_task.sequence_num = delayed_task_sequence_number_++; |
delayed_task_queue_.push(pending_task); |
TraceQueueSize(true); |
// If we changed the topmost task, then it is time to reschedule. |
- if (delayed_task_queue_.top().task.Equals(pending_task.task)) { |
- LazyNow lazy_now(now); |
- ScheduleDelayedWorkLocked(&lazy_now); |
- } |
+ if (delayed_task_queue_.top().task.Equals(pending_task.task)) |
+ ScheduleDelayedWorkLocked(lazy_now); |
return true; |
} |
EnqueueTaskLocked(pending_task); |
return true; |
} |
-void TaskQueue::MoveReadyDelayedTasksToIncomingQueue() { |
+void TaskQueueImpl::MoveReadyDelayedTasksToIncomingQueue() { |
DCHECK(main_thread_checker_.CalledOnValidThread()); |
base::AutoLock lock(lock_); |
if (!task_queue_manager_) |
@@ -227,7 +268,8 @@ void TaskQueue::MoveReadyDelayedTasksToIncomingQueue() { |
MoveReadyDelayedTasksToIncomingQueueLocked(&lazy_now); |
} |
-void TaskQueue::MoveReadyDelayedTasksToIncomingQueueLocked(LazyNow* lazy_now) { |
+void TaskQueueImpl::MoveReadyDelayedTasksToIncomingQueueLocked( |
+ LazyNow* lazy_now) { |
lock_.AssertAcquired(); |
// Enqueue all delayed tasks that should be running now. |
while (!delayed_task_queue_.empty() && |
@@ -241,12 +283,12 @@ void TaskQueue::MoveReadyDelayedTasksToIncomingQueueLocked(LazyNow* lazy_now) { |
ScheduleDelayedWorkLocked(lazy_now); |
} |
-void TaskQueue::ScheduleDelayedWorkLocked(LazyNow* lazy_now) { |
+void TaskQueueImpl::ScheduleDelayedWorkLocked(LazyNow* lazy_now) { |
lock_.AssertAcquired(); |
// Any remaining tasks are in the future, so queue a task to kick them. |
if (!delayed_task_queue_.empty()) { |
base::TimeTicks next_run_time = delayed_task_queue_.top().delayed_run_time; |
- DCHECK_GT(next_run_time, lazy_now->Now()); |
+ DCHECK_GE(next_run_time, lazy_now->Now()); |
// Make sure we don't have more than one |
// MoveReadyDelayedTasksToIncomingQueue posted for a particular scheduled |
// run time (note it's fine to have multiple ones in flight for distinct |
@@ -257,12 +299,13 @@ void TaskQueue::ScheduleDelayedWorkLocked(LazyNow* lazy_now) { |
base::TimeDelta delay = next_run_time - lazy_now->Now(); |
task_queue_manager_->PostDelayedTask( |
FROM_HERE, |
- Bind(&TaskQueue::MoveReadyDelayedTasksToIncomingQueue, this), delay); |
+ Bind(&TaskQueueImpl::MoveReadyDelayedTasksToIncomingQueue, this), |
+ delay); |
} |
} |
} |
-TaskQueueManager::QueueState TaskQueue::GetQueueState() const { |
+TaskQueueManager::QueueState TaskQueueImpl::GetQueueState() const { |
DCHECK(main_thread_checker_.CalledOnValidThread()); |
if (!work_queue_.empty()) |
return TaskQueueManager::QueueState::HAS_WORK; |
@@ -277,7 +320,7 @@ TaskQueueManager::QueueState TaskQueue::GetQueueState() const { |
} |
} |
-bool TaskQueue::TaskIsOlderThanQueuedTasks(const base::PendingTask* task) { |
+bool TaskQueueImpl::TaskIsOlderThanQueuedTasks(const base::PendingTask* task) { |
lock_.AssertAcquired(); |
// A null task is passed when UpdateQueue is called before any task is run. |
// In this case we don't want to pump an after_wakeup queue, so return true |
@@ -299,7 +342,7 @@ bool TaskQueue::TaskIsOlderThanQueuedTasks(const base::PendingTask* task) { |
return oldest_queued_task < *task; |
} |
-bool TaskQueue::ShouldAutoPumpQueueLocked( |
+bool TaskQueueImpl::ShouldAutoPumpQueueLocked( |
bool should_trigger_wakeup, |
const base::PendingTask* previous_task) { |
lock_.AssertAcquired(); |
@@ -313,7 +356,7 @@ bool TaskQueue::ShouldAutoPumpQueueLocked( |
return true; |
} |
-bool TaskQueue::NextPendingDelayedTaskRunTime( |
+bool TaskQueueImpl::NextPendingDelayedTaskRunTime( |
base::TimeTicks* next_pending_delayed_task) { |
base::AutoLock lock(lock_); |
if (delayed_task_queue_.empty()) |
@@ -322,9 +365,9 @@ bool TaskQueue::NextPendingDelayedTaskRunTime( |
return true; |
} |
-bool TaskQueue::UpdateWorkQueue(LazyNow* lazy_now, |
- bool should_trigger_wakeup, |
- const base::PendingTask* previous_task) { |
+bool TaskQueueImpl::UpdateWorkQueue(LazyNow* lazy_now, |
+ bool should_trigger_wakeup, |
+ const base::PendingTask* previous_task) { |
if (!work_queue_.empty()) |
return true; |
@@ -339,14 +382,14 @@ bool TaskQueue::UpdateWorkQueue(LazyNow* lazy_now, |
} |
} |
-base::PendingTask TaskQueue::TakeTaskFromWorkQueue() { |
+base::PendingTask TaskQueueImpl::TakeTaskFromWorkQueue() { |
base::PendingTask pending_task = work_queue_.front(); |
work_queue_.pop(); |
TraceQueueSize(false); |
return pending_task; |
} |
-void TaskQueue::TraceQueueSize(bool is_locked) const { |
+void TaskQueueImpl::TraceQueueSize(bool is_locked) const { |
bool is_tracing; |
TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, |
&is_tracing); |
@@ -363,7 +406,7 @@ void TaskQueue::TraceQueueSize(bool is_locked) const { |
lock_.Release(); |
} |
-void TaskQueue::EnqueueTaskLocked(const base::PendingTask& pending_task) { |
+void TaskQueueImpl::EnqueueTaskLocked(const base::PendingTask& pending_task) { |
lock_.AssertAcquired(); |
if (!task_queue_manager_) |
return; |
@@ -382,7 +425,7 @@ void TaskQueue::EnqueueTaskLocked(const base::PendingTask& pending_task) { |
TraceQueueSize(true); |
} |
-void TaskQueue::SetPumpPolicy(TaskQueueManager::PumpPolicy pump_policy) { |
+void TaskQueueImpl::SetPumpPolicy(TaskQueueManager::PumpPolicy pump_policy) { |
base::AutoLock lock(lock_); |
if (pump_policy == TaskQueueManager::PumpPolicy::AUTO && |
pump_policy_ != TaskQueueManager::PumpPolicy::AUTO) { |
@@ -391,7 +434,7 @@ void TaskQueue::SetPumpPolicy(TaskQueueManager::PumpPolicy pump_policy) { |
pump_policy_ = pump_policy; |
} |
-void TaskQueue::PumpQueueLocked() { |
+void TaskQueueImpl::PumpQueueLocked() { |
lock_.AssertAcquired(); |
if (task_queue_manager_) { |
LazyNow lazy_now(task_queue_manager_); |
@@ -405,12 +448,12 @@ void TaskQueue::PumpQueueLocked() { |
task_queue_manager_->MaybePostDoWorkOnMainRunner(); |
} |
-void TaskQueue::PumpQueue() { |
+void TaskQueueImpl::PumpQueue() { |
base::AutoLock lock(lock_); |
PumpQueueLocked(); |
} |
-void TaskQueue::AsValueInto(base::trace_event::TracedValue* state) const { |
+void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { |
base::AutoLock lock(lock_); |
state->BeginDictionary(); |
if (name_) |
@@ -440,8 +483,8 @@ void TaskQueue::AsValueInto(base::trace_event::TracedValue* state) const { |
} |
// static |
-void TaskQueue::QueueAsValueInto(const base::TaskQueue& queue, |
- base::trace_event::TracedValue* state) { |
+void TaskQueueImpl::QueueAsValueInto(const base::TaskQueue& queue, |
+ base::trace_event::TracedValue* state) { |
base::TaskQueue queue_copy(queue); |
while (!queue_copy.empty()) { |
TaskAsValueInto(queue_copy.front(), state); |
@@ -450,8 +493,8 @@ void TaskQueue::QueueAsValueInto(const base::TaskQueue& queue, |
} |
// static |
-void TaskQueue::QueueAsValueInto(const base::DelayedTaskQueue& queue, |
- base::trace_event::TracedValue* state) { |
+void TaskQueueImpl::QueueAsValueInto(const base::DelayedTaskQueue& queue, |
+ base::trace_event::TracedValue* state) { |
base::DelayedTaskQueue queue_copy(queue); |
while (!queue_copy.empty()) { |
TaskAsValueInto(queue_copy.top(), state); |
@@ -460,8 +503,8 @@ void TaskQueue::QueueAsValueInto(const base::DelayedTaskQueue& queue, |
} |
// static |
-void TaskQueue::TaskAsValueInto(const base::PendingTask& task, |
- base::trace_event::TracedValue* state) { |
+void TaskQueueImpl::TaskAsValueInto(const base::PendingTask& task, |
+ base::trace_event::TracedValue* state) { |
state->BeginDictionary(); |
state->SetString("posted_from", task.posted_from.ToString()); |
state->SetInteger("sequence_num", task.sequence_num); |
@@ -498,10 +541,10 @@ TaskQueueManager::TaskQueueManager( |
"TaskQueueManager", this); |
for (size_t i = 0; i < task_queue_count; i++) { |
- scoped_refptr<internal::TaskQueue> queue(make_scoped_refptr( |
- new internal::TaskQueue(this, |
- disabled_by_default_tracing_category, |
- disabled_by_default_verbose_tracing_category))); |
+ scoped_refptr<internal::TaskQueueImpl> queue( |
+ make_scoped_refptr(new internal::TaskQueueImpl( |
+ this, disabled_by_default_tracing_category, |
+ disabled_by_default_verbose_tracing_category))); |
queues_.push_back(queue); |
} |
@@ -525,13 +568,13 @@ TaskQueueManager::~TaskQueueManager() { |
selector_->SetTaskQueueSelectorObserver(nullptr); |
} |
-internal::TaskQueue* TaskQueueManager::Queue(size_t queue_index) const { |
+internal::TaskQueueImpl* TaskQueueManager::Queue(size_t queue_index) const { |
DCHECK_LT(queue_index, queues_.size()); |
return queues_[queue_index].get(); |
} |
-scoped_refptr<base::SingleThreadTaskRunner> |
-TaskQueueManager::TaskRunnerForQueue(size_t queue_index) const { |
+scoped_refptr<TaskQueue> TaskQueueManager::TaskRunnerForQueue( |
+ size_t queue_index) const { |
return Queue(queue_index); |
} |
@@ -570,20 +613,20 @@ base::TimeTicks TaskQueueManager::NextPendingDelayedTaskRunTime() { |
void TaskQueueManager::SetPumpPolicy(size_t queue_index, |
PumpPolicy pump_policy) { |
DCHECK(main_thread_checker_.CalledOnValidThread()); |
- internal::TaskQueue* queue = Queue(queue_index); |
+ internal::TaskQueueImpl* queue = Queue(queue_index); |
queue->SetPumpPolicy(pump_policy); |
} |
void TaskQueueManager::SetWakeupPolicy(size_t queue_index, |
WakeupPolicy wakeup_policy) { |
DCHECK(main_thread_checker_.CalledOnValidThread()); |
- internal::TaskQueue* queue = Queue(queue_index); |
+ internal::TaskQueueImpl* queue = Queue(queue_index); |
queue->set_wakeup_policy(wakeup_policy); |
} |
void TaskQueueManager::PumpQueue(size_t queue_index) { |
DCHECK(main_thread_checker_.CalledOnValidThread()); |
- internal::TaskQueue* queue = Queue(queue_index); |
+ internal::TaskQueueImpl* queue = Queue(queue_index); |
queue->PumpQueue(); |
} |
@@ -673,7 +716,7 @@ bool TaskQueueManager::ProcessTaskFromWorkQueue( |
base::PendingTask* previous_task) { |
DCHECK(main_thread_checker_.CalledOnValidThread()); |
scoped_refptr<DeletionSentinel> protect(deletion_sentinel_); |
- internal::TaskQueue* queue = Queue(queue_index); |
+ internal::TaskQueueImpl* queue = Queue(queue_index); |
base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); |
task_was_run_bitmap_ |= UINT64_C(1) << queue_index; |
if (!pending_task.nestable && main_task_runner_->IsNested()) { |
@@ -713,13 +756,13 @@ bool TaskQueueManager::PostDelayedTask( |
const tracked_objects::Location& from_here, |
const base::Closure& task, |
base::TimeDelta delay) { |
- DCHECK(delay > base::TimeDelta()); |
+ DCHECK_GE(delay, base::TimeDelta()); |
return main_task_runner_->PostDelayedTask(from_here, task, delay); |
} |
void TaskQueueManager::SetQueueName(size_t queue_index, const char* name) { |
DCHECK(main_thread_checker_.CalledOnValidThread()); |
- internal::TaskQueue* queue = Queue(queue_index); |
+ internal::TaskQueueImpl* queue = Queue(queue_index); |
queue->set_name(name); |
} |