Index: third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc |
diff --git a/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc b/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc |
index 406b9598ad81fbbedfe67b11905675c9b9881d8b..0987a2de209026d817ecce64ec9a46c58278ac77 100644 |
--- a/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc |
+++ b/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc |
@@ -25,9 +25,9 @@ IdleHelper::IdleHelper( |
base::TimeDelta required_quiescence_duration_before_long_idle_period) |
: helper_(helper), |
delegate_(delegate), |
- idle_queue_( |
- helper_->NewTaskQueue(TaskQueue::Spec("idle_tq").SetPumpPolicy( |
- TaskQueue::PumpPolicy::MANUAL))), |
+ idle_queue_(helper_->NewTaskQueue(TaskQueue::Spec("idle_tq"))), |
+ non_nestable_idle_queue_( |
+ helper_->NewTaskQueue(TaskQueue::Spec("non_nestable_idle_tq"))), |
state_(helper, |
delegate, |
tracing_category, |
@@ -43,13 +43,18 @@ IdleHelper::IdleHelper( |
base::Bind(&IdleHelper::EnableLongIdlePeriod, weak_idle_helper_ptr_)); |
on_idle_task_posted_closure_.Reset(base::Bind( |
&IdleHelper::OnIdleTaskPostedOnMainThread, weak_idle_helper_ptr_)); |
+ disable_idle_queue_closure_.Reset( |
+ base::Bind(&IdleHelper::DisableIdleTaskQueueTask, weak_idle_helper_ptr_)); |
+ disable_non_nestable_idle_queue_closure_.Reset(base::Bind( |
+ &IdleHelper::DisableNonNestableIdleTaskQueueTask, weak_idle_helper_ptr_)); |
idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner( |
- idle_queue_, helper_->ControlAfterWakeUpTaskRunner(), this, |
- tracing_category)); |
+ idle_queue_, non_nestable_idle_queue_, this, tracing_category)); |
idle_queue_->SetQueueEnabled(false); |
idle_queue_->SetQueuePriority(TaskQueue::BEST_EFFORT_PRIORITY); |
+ non_nestable_idle_queue_->SetQueueEnabled(false); |
+ non_nestable_idle_queue_->SetQueuePriority(TaskQueue::BEST_EFFORT_PRIORITY); |
helper_->AddTaskObserver(this); |
} |
@@ -62,6 +67,20 @@ IdleHelper::Delegate::Delegate() {} |
IdleHelper::Delegate::~Delegate() {} |
+void IdleHelper::DisableIdleTaskQueueTask() { |
+ idle_queue_->SetQueueEnabled(false); |
+ if (IsInLongIdlePeriod(state_.idle_period_state())) { |
+ UpdateLongIdlePeriodStateAfterIdleTask(); |
+ } |
+} |
+ |
+void IdleHelper::DisableNonNestableIdleTaskQueueTask() { |
+ non_nestable_idle_queue_->SetQueueEnabled(false); |
+ if (IsInLongIdlePeriod(state_.idle_period_state())) { |
+ UpdateLongIdlePeriodStateAfterIdleTask(); |
+ } |
+} |
+ |
scoped_refptr<SingleThreadIdleTaskRunner> IdleHelper::IdleTaskRunner() { |
helper_->CheckOnValidThread(); |
return idle_task_runner_; |
@@ -115,8 +134,9 @@ bool IdleHelper::ShouldWaitForQuiescence() { |
return false; |
if (required_quiescence_duration_before_long_idle_period_ == |
- base::TimeDelta()) |
+ base::TimeDelta()) { |
return false; |
+ } |
bool system_is_quiescent = helper_->GetAndClearSystemIsQuiescentBit(); |
TRACE_EVENT1(disabled_by_default_tracing_category_, "ShouldWaitForQuiescence", |
@@ -174,9 +194,21 @@ void IdleHelper::StartIdlePeriod(IdlePeriodState new_state, |
} |
TRACE_EVENT0(disabled_by_default_tracing_category_, "StartIdlePeriod"); |
- idle_queue_->SetQueueEnabled(true); |
- LazyNow lazy_now(now); |
- idle_queue_->PumpQueue(&lazy_now, true); |
+ |
+ // Make sure any idle tasks poster after this do not run until the next idle |
+ // period. With nested message loops it's possible there are pending disable |
+ // tasks, we don't want that so cancel them. |
+ disable_idle_queue_closure_.Cancel(); |
+ disable_non_nestable_idle_queue_closure_.Cancel(); |
+ if (idle_queue_->HasPendingImmediateWork()) { |
+ idle_queue_->PostTask(FROM_HERE, disable_idle_queue_closure_.callback()); |
Sami
2016/08/25 15:54:12
I wonder if this could have a failure mode where w
alex clarke (OOO till 29th)
2016/08/26 13:29:08
I've replaced this mechanism with something akin t
|
+ idle_queue_->SetQueueEnabled(true); |
+ } |
+ if (non_nestable_idle_queue_->HasPendingImmediateWork()) { |
+ non_nestable_idle_queue_->PostNonNestableTask( |
+ FROM_HERE, disable_non_nestable_idle_queue_closure_.callback()); |
+ non_nestable_idle_queue_->SetQueueEnabled(true); |
+ } |
state_.UpdateState(new_state, idle_period_deadline, now); |
} |
@@ -192,7 +224,12 @@ void IdleHelper::EndIdlePeriod() { |
if (!IsInIdlePeriod(state_.idle_period_state())) |
return; |
+ // Cancel any pending calls to disable the idle queues in favor of disabling |
+ // now. |
+ disable_idle_queue_closure_.Cancel(); |
Sami
2016/08/25 15:54:13
This means we might not run UpdateLongIdlePeriodSt
alex clarke (OOO till 29th)
2016/08/26 13:29:08
Acknowledged.
|
+ disable_non_nestable_idle_queue_closure_.Cancel(); |
idle_queue_->SetQueueEnabled(false); |
+ non_nestable_idle_queue_->SetQueueEnabled(false); |
state_.UpdateState(IdlePeriodState::NOT_IN_IDLE_PERIOD, base::TimeTicks(), |
base::TimeTicks()); |
} |
@@ -230,7 +267,7 @@ void IdleHelper::UpdateLongIdlePeriodStateAfterIdleTask() { |
// new idle task is posted. |
state_.UpdateState(IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED, |
state_.idle_period_deadline(), base::TimeTicks()); |
- } else if (idle_queue_->NeedsPumping()) { |
+ } else if (!idle_queue_->IsEmpty()) { |
// If there is still idle work to do then just start the next idle period. |
base::TimeDelta next_long_idle_period_delay; |
if (state_.idle_period_state() == |
@@ -290,9 +327,6 @@ base::TimeTicks IdleHelper::WillProcessIdleTask() { |
void IdleHelper::DidProcessIdleTask() { |
helper_->CheckOnValidThread(); |
state_.TraceIdleIdleTaskEnd(); |
- if (IsInLongIdlePeriod(state_.idle_period_state())) { |
- UpdateLongIdlePeriodStateAfterIdleTask(); |
- } |
} |
// static |