1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef COMPONENTS_SCHEDULER_RENDERER_RENDERER_SCHEDULER_IMPL_H_
6 #define COMPONENTS_SCHEDULER_RENDERER_RENDERER_SCHEDULER_IMPL_H_
8 #include "base/atomicops.h"
9 #include "base/synchronization/lock.h"
10 #include "components/scheduler/child/idle_helper.h"
11 #include "components/scheduler/child/pollable_thread_safe_flag.h"
12 #include "components/scheduler/child/scheduler_helper.h"
13 #include "components/scheduler/renderer/deadline_task_runner.h"
14 #include "components/scheduler/renderer/renderer_scheduler.h"
15 #include "components/scheduler/renderer/task_cost_estimator.h"
16 #include "components/scheduler/renderer/user_model.h"
17 #include "components/scheduler/scheduler_export.h"
20 namespace trace_event
{
21 class ConvertableToTraceFormat
;
27 class SCHEDULER_EXPORT RendererSchedulerImpl
: public RendererScheduler
,
28 public IdleHelper::Delegate
{
30 RendererSchedulerImpl(
31 scoped_refptr
<SchedulerTaskRunnerDelegate
> main_task_runner
);
32 ~RendererSchedulerImpl() override
;
34 // RendererScheduler implementation:
35 scoped_refptr
<TaskQueue
> DefaultTaskRunner() override
;
36 scoped_refptr
<SingleThreadIdleTaskRunner
> IdleTaskRunner() override
;
37 scoped_refptr
<base::SingleThreadTaskRunner
> CompositorTaskRunner() override
;
38 scoped_refptr
<base::SingleThreadTaskRunner
> LoadingTaskRunner() override
;
39 scoped_refptr
<TaskQueue
> TimerTaskRunner() override
;
40 void WillBeginFrame(const cc::BeginFrameArgs
& args
) override
;
41 void BeginFrameNotExpectedSoon() override
;
42 void DidCommitFrameToCompositor() override
;
43 void DidHandleInputEventOnCompositorThread(
44 const blink::WebInputEvent
& web_input_event
,
45 InputEventState event_state
) override
;
46 void DidHandleInputEventOnMainThread(
47 const blink::WebInputEvent
& web_input_event
) override
;
48 void DidAnimateForInputOnCompositorThread() override
;
49 void OnRendererHidden() override
;
50 void OnRendererVisible() override
;
51 void OnRendererBackgrounded() override
;
52 void OnRendererForegrounded() override
;
53 void OnPageLoadStarted() override
;
54 bool IsHighPriorityWorkAnticipated() override
;
55 bool ShouldYieldForHighPriorityWork() override
;
56 bool CanExceedIdleDeadlineIfRequired() const override
;
57 void AddTaskObserver(base::MessageLoop::TaskObserver
* task_observer
) override
;
58 void RemoveTaskObserver(
59 base::MessageLoop::TaskObserver
* task_observer
) override
;
60 void Shutdown() override
;
61 void SuspendTimerQueue() override
;
62 void ResumeTimerQueue() override
;
63 void SetTimerQueueSuspensionWhenBackgroundedEnabled(bool enabled
) override
;
66 SchedulerHelper
* GetSchedulerHelperForTesting();
67 TaskCostEstimator
* GetLoadingTaskCostEstimatorForTesting();
68 TaskCostEstimator
* GetTimerTaskCostEstimatorForTesting();
69 base::TimeTicks
CurrentIdleTaskDeadlineForTesting() const;
72 friend class RendererSchedulerImplTest
;
73 friend class RendererSchedulerImplForTest
;
78 TaskQueue::QueuePriority compositor_queue_priority
;
79 TaskQueue::QueuePriority loading_queue_priority
;
80 TaskQueue::QueuePriority timer_queue_priority
;
81 TaskQueue::QueuePriority default_queue_priority
;
83 bool operator==(const Policy
& other
) const {
84 return compositor_queue_priority
== other
.compositor_queue_priority
&&
85 loading_queue_priority
== other
.loading_queue_priority
&&
86 timer_queue_priority
== other
.timer_queue_priority
&&
87 default_queue_priority
== other
.default_queue_priority
;
91 class PollableNeedsUpdateFlag
{
93 PollableNeedsUpdateFlag(base::Lock
* write_lock
);
94 ~PollableNeedsUpdateFlag();
96 // Set the flag. May only be called if |write_lock| is held.
97 void SetWhileLocked(bool value
);
99 // Returns true iff the flag is set to true.
103 base::subtle::Atomic32 flag_
;
104 base::Lock
* write_lock_
; // Not owned.
106 DISALLOW_COPY_AND_ASSIGN(PollableNeedsUpdateFlag
);
109 // IdleHelper::Delegate implementation:
110 bool CanEnterLongIdlePeriod(
112 base::TimeDelta
* next_long_idle_period_delay_out
) override
;
113 void IsNotQuiescent() override
{}
114 void OnIdlePeriodStarted() override
;
115 void OnIdlePeriodEnded() override
;
117 void EndIdlePeriod();
119 // Returns the serialized scheduler state for tracing.
120 scoped_refptr
<base::trace_event::ConvertableToTraceFormat
> AsValue(
121 base::TimeTicks optional_now
) const;
122 scoped_refptr
<base::trace_event::ConvertableToTraceFormat
> AsValueLocked(
123 base::TimeTicks optional_now
) const;
125 static bool ShouldPrioritizeInputEvent(
126 const blink::WebInputEvent
& web_input_event
);
128 // The amount of time which idle periods can continue being scheduled when the
129 // renderer has been hidden, before going to sleep for good.
130 static const int kEndIdleWhenHiddenDelayMillis
= 10000;
132 // The amount of time for which loading tasks will be prioritized over
133 // other tasks during the initial page load.
134 static const int kRailsInitialLoadingPrioritizationMillis
= 1000;
136 // For the purposes of deciding whether or not it's safe to turn timers and
137 // loading tasks on only in idle periods, we regard the system as being as
138 // being "idle period" starved if there hasn't been an idle period in the last
139 // 10 seconds. This was chosen to be long enough to cover most anticipated
141 static const int kIdlePeriodStarvationThresholdMillis
= 10000;
143 // The amount of time to wait before suspending shared timers after the
144 // renderer has been backgrounded. This is used only if background suspension
145 // of shared timers is enabled.
146 static const int kSuspendTimersWhenBackgroundedDelayMillis
= 5 * 60 * 1000;
148 // Schedules an immediate PolicyUpdate, if there isn't one already pending and
149 // sets |policy_may_need_update_|. Note |any_thread_lock_| must be
151 void EnsureUrgentPolicyUpdatePostedOnMainThread(
152 const tracked_objects::Location
& from_here
);
154 // Update the policy if a new signal has arrived. Must be called from the main
156 void MaybeUpdatePolicy();
158 // Locks |any_thread_lock_| and updates the scheduler policy. May early
159 // out if the policy is unchanged. Must be called from the main thread.
162 // Like UpdatePolicy, except it doesn't early out.
163 void ForceUpdatePolicy();
165 enum class UpdateType
{
166 MAY_EARLY_OUT_IF_POLICY_UNCHANGED
,
170 // The implelemtation of UpdatePolicy & ForceUpdatePolicy. It is allowed to
171 // early out if |update_type| is MAY_EARLY_OUT_IF_POLICY_UNCHANGED.
172 virtual void UpdatePolicyLocked(UpdateType update_type
);
174 // Helper for computing the use case. |expected_usecase_duration| will be
175 // filled with the amount of time after which the use case should be updated
176 // again. If the duration is zero, a new use case update should not be
177 // scheduled. Must be called with |any_thread_lock_| held. Can be called from
179 UseCase
ComputeCurrentUseCase(
181 base::TimeDelta
* expected_use_case_duration
) const;
183 // Works out if a gesture appears to be in progress based on the current
184 // input signals. Can be called from any thread.
185 bool InputSignalsSuggestGestureInProgress(base::TimeTicks now
) const;
187 // An input event of some sort happened, the policy may need updating.
188 void UpdateForInputEventOnCompositorThread(blink::WebInputEvent::Type type
,
189 InputEventState input_event_state
);
191 // Returns true if there has been at least one idle period in the last
192 // |kIdlePeriodStarvationThresholdMillis|.
193 bool HadAnIdlePeriodRecently(base::TimeTicks now
) const;
195 // Helpers for safely suspending/resuming the timer queue after a
196 // background/foreground signal.
197 void SuspendTimerQueueWhenBackgrounded();
198 void ResumeTimerQueueWhenForegrounded();
200 // The task cost estimators and the UserModel need to be reset upon page
201 // nagigation. This function does that. Must be called from the main thread.
202 void ResetForNavigationLocked();
204 SchedulerHelper helper_
;
205 IdleHelper idle_helper_
;
207 const scoped_refptr
<TaskQueue
> control_task_runner_
;
208 const scoped_refptr
<TaskQueue
> compositor_task_runner_
;
209 const scoped_refptr
<TaskQueue
> loading_task_runner_
;
210 const scoped_refptr
<TaskQueue
> timer_task_runner_
;
212 base::Closure update_policy_closure_
;
213 DeadlineTaskRunner delayed_update_policy_runner_
;
214 CancelableClosureHolder end_renderer_hidden_idle_period_closure_
;
215 CancelableClosureHolder suspend_timers_when_backgrounded_closure_
;
217 // We have decided to improve thread safety at the cost of some boilerplate
218 // (the accessors) for the following data members.
220 struct MainThreadOnly
{
224 TaskCostEstimator loading_task_cost_estimator
;
225 TaskCostEstimator timer_task_cost_estimator
;
226 cc::RollingTimeDeltaHistory short_idle_period_duration
;
227 UseCase current_use_case
;
228 Policy current_policy
;
229 base::TimeTicks current_policy_expiration_time
;
230 base::TimeTicks estimated_next_frame_begin
;
231 base::TimeDelta expected_short_idle_period_duration
;
232 int timer_queue_suspend_count
; // TIMER_TASK_QUEUE suspended if non-zero.
233 bool renderer_hidden
;
234 bool renderer_backgrounded
;
235 bool timer_queue_suspension_when_backgrounded_enabled
;
236 bool timer_queue_suspended_when_backgrounded
;
238 bool loading_tasks_seem_expensive
;
239 bool timer_tasks_seem_expensive
;
240 bool touchstart_expected_soon
;
241 bool have_seen_a_begin_main_frame
;
247 base::TimeTicks last_idle_period_end_time
;
248 base::TimeTicks rails_loading_priority_deadline
;
249 UserModel user_model
;
250 bool awaiting_touch_start_response
;
252 bool begin_main_frame_on_critical_path
;
255 struct CompositorThreadOnly
{
256 CompositorThreadOnly();
257 ~CompositorThreadOnly();
259 blink::WebInputEvent::Type last_input_type
;
260 scoped_ptr
<base::ThreadChecker
> compositor_thread_checker
;
262 void CheckOnValidThread() {
264 // We don't actually care which thread this called from, just so long as
266 if (!compositor_thread_checker
)
267 compositor_thread_checker
.reset(new base::ThreadChecker());
268 DCHECK(compositor_thread_checker
->CalledOnValidThread());
273 // Don't access main_thread_only_, instead use MainThreadOnly().
274 MainThreadOnly main_thread_only_
;
275 MainThreadOnly
& MainThreadOnly() {
276 helper_
.CheckOnValidThread();
277 return main_thread_only_
;
279 const struct MainThreadOnly
& MainThreadOnly() const {
280 helper_
.CheckOnValidThread();
281 return main_thread_only_
;
284 mutable base::Lock any_thread_lock_
;
285 // Don't access any_thread_, instead use AnyThread().
286 AnyThread any_thread_
;
287 AnyThread
& AnyThread() {
288 any_thread_lock_
.AssertAcquired();
291 const struct AnyThread
& AnyThread() const {
292 any_thread_lock_
.AssertAcquired();
296 // Don't access compositor_thread_only_, instead use CompositorThreadOnly().
297 CompositorThreadOnly compositor_thread_only_
;
298 CompositorThreadOnly
& CompositorThreadOnly() {
299 compositor_thread_only_
.CheckOnValidThread();
300 return compositor_thread_only_
;
303 PollableThreadSafeFlag policy_may_need_update_
;
304 base::WeakPtrFactory
<RendererSchedulerImpl
> weak_factory_
;
306 DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImpl
);
309 } // namespace scheduler
311 #endif // COMPONENTS_SCHEDULER_RENDERER_RENDERER_SCHEDULER_IMPL_H_