Index: components/scheduler/base/task_queue_impl.cc |
diff --git a/components/scheduler/base/task_queue_impl.cc b/components/scheduler/base/task_queue_impl.cc |
index 651770740e8a2f7ba6527c25fd042425b0eba6ea..a09e84da32190ae937afce0be47cc18a7a5d4e65 100644 |
--- a/components/scheduler/base/task_queue_impl.cc |
+++ b/components/scheduler/base/task_queue_impl.cc |
@@ -6,17 +6,19 @@ |
#include "components/scheduler/base/task_queue_manager.h" |
#include "components/scheduler/base/task_queue_manager_delegate.h" |
+#include "components/scheduler/base/time_domain.h" |
namespace scheduler { |
namespace internal { |
TaskQueueImpl::TaskQueueImpl( |
TaskQueueManager* task_queue_manager, |
+ const scoped_refptr<TimeDomain>& time_domain, |
const Spec& spec, |
const char* disabled_by_default_tracing_category, |
const char* disabled_by_default_verbose_tracing_category) |
: thread_id_(base::PlatformThread::CurrentId()), |
- any_thread_(task_queue_manager, spec.pump_policy), |
+ any_thread_(task_queue_manager, spec.pump_policy, time_domain), |
name_(spec.name), |
disabled_by_default_tracing_category_( |
disabled_by_default_tracing_category), |
@@ -25,7 +27,9 @@ TaskQueueImpl::TaskQueueImpl( |
main_thread_only_(task_queue_manager), |
wakeup_policy_(spec.wakeup_policy), |
should_monitor_quiescence_(spec.should_monitor_quiescence), |
- should_notify_observers_(spec.should_notify_observers) {} |
+ should_notify_observers_(spec.should_notify_observers) { |
+ DCHECK(time_domain.get()); |
+} |
TaskQueueImpl::~TaskQueueImpl() {} |
@@ -53,9 +57,13 @@ TaskQueueImpl::Task::Task(const tracked_objects::Location& posted_from, |
sequence_num = sequence_number; |
} |
-TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, |
- PumpPolicy pump_policy) |
- : task_queue_manager(task_queue_manager), pump_policy(pump_policy) {} |
+TaskQueueImpl::AnyThread::AnyThread( |
+ TaskQueueManager* task_queue_manager, |
+ PumpPolicy pump_policy, |
+ const scoped_refptr<TimeDomain>& time_domain) |
+ : task_queue_manager(task_queue_manager), |
+ pump_policy(pump_policy), |
+ time_domain(time_domain) {} |
TaskQueueImpl::AnyThread::~AnyThread() {} |
@@ -70,6 +78,8 @@ void TaskQueueImpl::UnregisterTaskQueue() { |
base::AutoLock lock(any_thread_lock_); |
if (!any_thread().task_queue_manager) |
return; |
+ any_thread().time_domain->UnregisterQueue(this); |
+ any_thread().time_domain = nullptr; |
any_thread().task_queue_manager->UnregisterTaskQueue(this); |
any_thread().task_queue_manager = nullptr; |
@@ -104,7 +114,7 @@ bool TaskQueueImpl::PostDelayedTaskAt( |
base::AutoLock lock(any_thread_lock_); |
if (!any_thread().task_queue_manager) |
return false; |
- LazyNow lazy_now(any_thread().task_queue_manager->delegate().get()); |
+ LazyNow lazy_now(any_thread().time_domain->CreateLazyNow()); |
return PostDelayedTaskLocked(&lazy_now, from_here, task, desired_run_time, |
TaskType::NORMAL); |
} |
@@ -117,7 +127,7 @@ bool TaskQueueImpl::PostDelayedTaskImpl( |
base::AutoLock lock(any_thread_lock_); |
if (!any_thread().task_queue_manager) |
return false; |
- LazyNow lazy_now(any_thread().task_queue_manager->delegate().get()); |
+ LazyNow lazy_now(any_thread().time_domain->CreateLazyNow()); |
base::TimeTicks desired_run_time; |
if (delay > base::TimeDelta()) |
desired_run_time = lazy_now.Now() + delay; |
@@ -143,8 +153,22 @@ bool TaskQueueImpl::PostDelayedTaskLocked( |
any_thread().delayed_task_queue.push(pending_task); |
TraceQueueSize(true); |
// Schedule a later call to MoveReadyDelayedTasksToIncomingQueue. |
- any_thread().task_queue_manager->ScheduleDelayedWork(this, desired_run_time, |
- lazy_now); |
+ if (base::PlatformThread::CurrentId() == thread_id_) { |
+ any_thread().time_domain->ScheduleDelayedWork(this, desired_run_time, |
+ lazy_now); |
+ } else { |
+ // NOTE posting a delayed task from a different thread is not expected to |
+ // be common. This pathway is less optimal than perhaps it could be |
+ // because it causes two main thread tasks to be run. Should this |
+ // assumption prove to be false in future, we may need to revisit this. |
+ Task thread_hop_task( |
+ FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, |
+ any_thread().time_domain, desired_run_time), |
+ any_thread().task_queue_manager->GetNextSequenceNumber(), true); |
+ thread_hop_task.set_enqueue_order(thread_hop_task.sequence_num); |
+ any_thread().task_queue_manager->DidQueueTask(thread_hop_task); |
+ EnqueueTaskLocked(thread_hop_task); |
+ } |
return true; |
} |
pending_task.set_enqueue_order(pending_task.sequence_num); |
@@ -152,6 +176,14 @@ bool TaskQueueImpl::PostDelayedTaskLocked( |
return true; |
} |
+void TaskQueueImpl::ScheduleDelayedWorkTask( |
+ const scoped_refptr<TimeDomain> time_domain, |
+ base::TimeTicks desired_run_time) { |
+ DCHECK(main_thread_checker_.CalledOnValidThread()); |
+ LazyNow lazy_now(time_domain->CreateLazyNow()); |
+ time_domain->ScheduleDelayedWork(this, desired_run_time, &lazy_now); |
+} |
+ |
void TaskQueueImpl::MoveReadyDelayedTasksToIncomingQueue(LazyNow* lazy_now) { |
base::AutoLock lock(any_thread_lock_); |
if (!any_thread().task_queue_manager) |
@@ -222,16 +254,6 @@ bool TaskQueueImpl::ShouldAutoPumpQueueLocked(bool should_trigger_wakeup, |
return true; |
} |
-bool TaskQueueImpl::NextPendingDelayedTaskRunTime( |
- base::TimeTicks* next_pending_delayed_task) { |
- base::AutoLock lock(any_thread_lock_); |
- if (any_thread().delayed_task_queue.empty()) |
- return false; |
- *next_pending_delayed_task = |
- any_thread().delayed_task_queue.top().delayed_run_time; |
- return true; |
-} |
- |
void TaskQueueImpl::UpdateWorkQueue(LazyNow* lazy_now, |
bool should_trigger_wakeup, |
const Task* previous_task) { |
@@ -241,10 +263,9 @@ void TaskQueueImpl::UpdateWorkQueue(LazyNow* lazy_now, |
return; |
MoveReadyDelayedTasksToIncomingQueueLocked(lazy_now); |
std::swap(main_thread_only().work_queue, any_thread().incoming_queue); |
- // |any_thread().incoming_queue| is now empty so |
- // TaskQueueManager::UpdateQueues no longer needs to consider |
- // this queue for reloading. |
- any_thread().task_queue_manager->UnregisterAsUpdatableTaskQueue(this); |
+ // |any_thread().incoming_queue| is now empty so TimeDomain::UpdateQueues |
+ // no longer needs to consider this queue for reloading. |
+ any_thread().time_domain->UnregisterAsUpdatableTaskQueue(this); |
if (!main_thread_only().work_queue.empty()) { |
DCHECK(any_thread().task_queue_manager); |
any_thread().task_queue_manager->selector_.GetTaskQueueSets()->OnPushQueue( |
@@ -287,7 +308,7 @@ void TaskQueueImpl::EnqueueTaskLocked(const Task& pending_task) { |
if (!any_thread().task_queue_manager) |
return; |
if (any_thread().incoming_queue.empty()) |
- any_thread().task_queue_manager->RegisterAsUpdatableTaskQueue(this); |
+ any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); |
if (any_thread().pump_policy == PumpPolicy::AUTO && |
any_thread().incoming_queue.empty()) { |
any_thread().task_queue_manager->MaybePostDoWorkOnMainRunner(); |
@@ -297,11 +318,17 @@ void TaskQueueImpl::EnqueueTaskLocked(const Task& pending_task) { |
TraceQueueSize(true); |
} |
+// TODO(alexclarke): Consider merging EnqueueTaskLocked & |
+// EnqueueDelayedTaskLocked. |
void TaskQueueImpl::EnqueueDelayedTaskLocked(const Task& pending_task) { |
if (!any_thread().task_queue_manager) |
return; |
if (any_thread().incoming_queue.empty()) |
- any_thread().task_queue_manager->RegisterAsUpdatableTaskQueue(this); |
+ any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); |
+ if (any_thread().pump_policy == PumpPolicy::AUTO && |
+ any_thread().incoming_queue.empty()) { |
+ any_thread().task_queue_manager->MaybePostDoWorkOnMainRunner(); |
+ } |
// TODO(alexclarke): consider std::move() when allowed. |
any_thread().incoming_queue.push(pending_task); |
any_thread().incoming_queue.back().set_enqueue_order( |
@@ -322,7 +349,7 @@ void TaskQueueImpl::PumpQueueLocked() { |
if (!any_thread().task_queue_manager) |
return; |
- LazyNow lazy_now(any_thread().task_queue_manager->delegate().get()); |
+ LazyNow lazy_now(any_thread().time_domain->CreateLazyNow()); |
MoveReadyDelayedTasksToIncomingQueueLocked(&lazy_now); |
bool was_empty = main_thread_only().work_queue.empty(); |
@@ -331,9 +358,9 @@ void TaskQueueImpl::PumpQueueLocked() { |
main_thread_only().work_queue.push(any_thread().incoming_queue.front()); |
any_thread().incoming_queue.pop(); |
} |
- // |incoming_queue| is now empty so TaskQueueManager::UpdateQueues no longer |
- // needs to consider this queue for reloading. |
- any_thread().task_queue_manager->UnregisterAsUpdatableTaskQueue(this); |
+ // |incoming_queue| is now empty so TimeDomain::UpdateQueues no longer needs |
+ // to consider this queue for reloading. |
+ any_thread().time_domain->UnregisterAsUpdatableTaskQueue(this); |
if (!main_thread_only().work_queue.empty()) { |
if (was_empty) { |
any_thread() |
@@ -430,6 +457,7 @@ void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { |
base::AutoLock lock(any_thread_lock_); |
state->BeginDictionary(); |
state->SetString("name", GetName()); |
+ state->SetString("time_domain_name", any_thread().time_domain->GetName()); |
state->SetString("pump_policy", PumpPolicyToString(any_thread().pump_policy)); |
state->SetString("wakeup_policy", WakeupPolicyToString(wakeup_policy_)); |
bool verbose_tracing_enabled = false; |
@@ -481,6 +509,17 @@ void TaskQueueImpl::NotifyDidProcessTask( |
DidProcessTask(pending_task)); |
} |
+void TaskQueueImpl::SetTimeDomain( |
+ const scoped_refptr<TimeDomain>& time_domain) { |
+ base::AutoLock lock(any_thread_lock_); |
+ DCHECK(main_thread_checker_.CalledOnValidThread()); |
+ if (time_domain == any_thread().time_domain) |
+ return; |
+ |
+ any_thread().time_domain->MigrateQueue(this, time_domain.get()); |
+ any_thread().time_domain = time_domain; |
+} |
+ |
// static |
void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, |
base::trace_event::TracedValue* state) { |
@@ -516,5 +555,10 @@ void TaskQueueImpl::TaskAsValueInto(const Task& task, |
state->EndDictionary(); |
} |
+size_t TaskQueueImpl::IncomingQueueSizeForTest() const { |
+ base::AutoLock lock(any_thread_lock_); |
+ return any_thread().incoming_queue.size(); |
+} |
+ |
} // namespace internal |
} // namespace scheduler |