Chromium Code Reviews| Index: components/scheduler/renderer/throttling_helper.cc |
| diff --git a/components/scheduler/renderer/throttling_helper.cc b/components/scheduler/renderer/throttling_helper.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b80d5dd4156ee884af39fcf1512df2d7b072c1e2 |
| --- /dev/null |
| +++ b/components/scheduler/renderer/throttling_helper.cc |
| @@ -0,0 +1,120 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "components/scheduler/renderer/throttling_helper.h" |
| + |
| +#include "base/logging.h" |
| +#include "components/scheduler/base/real_time_domain.h" |
| +#include "components/scheduler/base/virtual_time_domain.h" |
| +#include "components/scheduler/child/scheduler_tqm_delegate.h" |
| +#include "components/scheduler/renderer/renderer_scheduler_impl.h" |
| +#include "components/scheduler/renderer/web_frame_scheduler_impl.h" |
| +#include "third_party/WebKit/public/platform/WebFrameScheduler.h" |
| + |
| +namespace scheduler { |
| + |
| +ThrottlingHelper::ThrottlingHelper(RendererSchedulerImpl* renderer_scheduler, |
| + const char* tracing_category) |
| + : renderer_scheduler_(renderer_scheduler), |
| + tracing_category_(tracing_category), |
| + time_domain_(new VirtualTimeDomain(renderer_scheduler->real_time_domain() |
| + ->CreateLazyNow() |
| + .Now())), |
| + pending_pump_throttled_tasks_(false), |
| + work_to_do_(false), |
| + weak_factory_(this) { |
| + pump_throttled_tasks_closure_ = base::Bind( |
| + &ThrottlingHelper::PumpThrottledTasks, weak_factory_.GetWeakPtr()); |
| + renderer_scheduler_->RegisterTimeDomain(time_domain_); |
| + time_domain_->SetObserver(this); |
| +} |
| + |
| +ThrottlingHelper::~ThrottlingHelper() { |
| + time_domain_->SetObserver(nullptr); |
| + renderer_scheduler_->UnregisterTimeDomain(time_domain_); |
| +} |
| + |
| +void ThrottlingHelper::ThrottleBackgroundFrame( |
| + WebFrameSchedulerImpl* frame_scheduler) { |
| + background_frame_schedulers_.insert(frame_scheduler); |
| + frame_scheduler->SetPageInBackground(true); |
| + |
| + { |
| + base::AutoLock lock(lock_); |
| + work_to_do_ |= frame_scheduler->PendingBackgroundTasks(); |
| + MaybeSchedulePumpThrottledTasksLocked(); |
| + } |
| +} |
| + |
| +void ThrottlingHelper::UnthrottleForegroundFrame( |
| + WebFrameSchedulerImpl* frame_scheduler) { |
| + background_frame_schedulers_.erase(frame_scheduler); |
| + frame_scheduler->SetPageInBackground(false); |
| + |
| + if (background_frame_schedulers_.empty()) { |
| + base::AutoLock lock(lock_); |
| + work_to_do_ = false; |
| + } |
| +} |
| + |
| +void ThrottlingHelper::Unregister(WebFrameSchedulerImpl* frame_scheduler) { |
| + background_frame_schedulers_.erase(frame_scheduler); |
| + |
| + if (background_frame_schedulers_.empty()) { |
| + base::AutoLock lock(lock_); |
| + work_to_do_ = false; |
| + } |
| +} |
| + |
| +void ThrottlingHelper::OnRegisterAsUpdatableTaskQueue() { |
| + base::AutoLock lock(lock_); |
| + TRACE_EVENT0(tracing_category_, |
| + "ThrottlingHelper::OnRegisterAsUpdatableTaskQueue"); |
| + work_to_do_ = true; |
| + MaybeSchedulePumpThrottledTasksLocked(); |
| +} |
| + |
| +void ThrottlingHelper::OnRequestWakeup() { |
| + base::AutoLock lock(lock_); |
| + TRACE_EVENT0(tracing_category_, |
| + "ThrottlingHelper::OnRegisterAsUpdatableTaskQueue"); |
|
Sami
2015/11/24 12:48:48
OnRequestWakeup
alex clarke (OOO till 29th)
2015/11/25 12:29:36
Done.
|
| + work_to_do_ = true; |
| + MaybeSchedulePumpThrottledTasksLocked(); |
| +} |
| + |
| +void ThrottlingHelper::PumpThrottledTasks() { |
| + TRACE_EVENT0(tracing_category_, "ThrottlingHelper::PumpThrottledTasks"); |
| + time_domain_->AdvanceTo( |
| + renderer_scheduler_->real_time_domain()->CreateLazyNow().Now()); |
| + work_to_do_ = false; |
|
Sami
2015/11/24 12:48:48
Should this be inside the lock too?
alex clarke (OOO till 29th)
2015/11/25 12:29:36
I got rid of the locking.
|
| + for (WebFrameSchedulerImpl* frame_scheduler : background_frame_schedulers_) { |
| + work_to_do_ |= frame_scheduler->PumpBackgroundTasks(); |
| + } |
| + |
| + { |
| + base::AutoLock lock(lock_); |
| + pending_pump_throttled_tasks_ = false; |
| + MaybeSchedulePumpThrottledTasksLocked(); |
| + } |
| +} |
| + |
| +/* static */ |
| +base::TimeDelta ThrottlingHelper::DelayToNextRunTimeInSeconds( |
| + base::TimeTicks now) { |
| + const base::TimeDelta one_second = base::TimeDelta::FromSeconds(1); |
|
Sami
2015/11/24 12:48:48
Could we use TimeTicks::SnappedToNextTick?
alex clarke (OOO till 29th)
2015/11/25 12:29:36
It doesn't seem to do what I wanted. Specifically
Sami
2015/11/25 17:12:25
Ah, different boundary condition, got it.
alex clarke (OOO till 29th)
2015/11/26 18:43:27
Acknowledged.
|
| + return one_second - ((now - base::TimeTicks()) % one_second); |
| +} |
| + |
| +void ThrottlingHelper::MaybeSchedulePumpThrottledTasksLocked() { |
| + if (pending_pump_throttled_tasks_ || !work_to_do_) |
|
Sami
2015/11/24 12:48:48
Assert that we're holding the lock?
alex clarke (OOO till 29th)
2015/11/25 12:29:36
Acknowledged.
|
| + return; |
| + |
| + pending_pump_throttled_tasks_ = true; |
| + renderer_scheduler_->ControlTaskRunner()->PostDelayedTask( |
| + FROM_HERE, pump_throttled_tasks_closure_, |
| + DelayToNextRunTimeInSeconds( |
| + renderer_scheduler_->real_time_domain()->CreateLazyNow().Now())); |
|
Sami
2015/11/24 12:48:48
Looks like real_time_domain() is main thread only
alex clarke (OOO till 29th)
2015/11/25 12:29:36
Acknowledged.
|
| +} |
| + |
| +} // namespace scheduler |