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/scheduler_export.h"
19 namespace trace_event
{
20 class ConvertableToTraceFormat
;
26 class SCHEDULER_EXPORT RendererSchedulerImpl
: public RendererScheduler
,
27 public IdleHelper::Delegate
{
29 RendererSchedulerImpl(
30 scoped_refptr
<SchedulerTaskRunnerDelegate
> main_task_runner
);
31 ~RendererSchedulerImpl() override
;
33 // RendererScheduler implementation:
34 scoped_refptr
<TaskQueue
> DefaultTaskRunner() override
;
35 scoped_refptr
<SingleThreadIdleTaskRunner
> IdleTaskRunner() override
;
36 scoped_refptr
<base::SingleThreadTaskRunner
> CompositorTaskRunner() override
;
37 scoped_refptr
<base::SingleThreadTaskRunner
> LoadingTaskRunner() override
;
38 scoped_refptr
<TaskQueue
> TimerTaskRunner() override
;
39 void WillBeginFrame(const cc::BeginFrameArgs
& args
) override
;
40 void BeginFrameNotExpectedSoon() override
;
41 void DidCommitFrameToCompositor() override
;
42 void DidHandleInputEventOnCompositorThread(
43 const blink::WebInputEvent
& web_input_event
,
44 InputEventState event_state
) override
;
45 void DidHandleInputEventOnMainThread(
46 const blink::WebInputEvent
& web_input_event
) override
;
47 void DidAnimateForInputOnCompositorThread() override
;
48 void OnRendererHidden() override
;
49 void OnRendererVisible() override
;
50 void OnPageLoadStarted() override
;
51 bool IsHighPriorityWorkAnticipated() override
;
52 bool ShouldYieldForHighPriorityWork() override
;
53 bool CanExceedIdleDeadlineIfRequired() const override
;
54 void AddTaskObserver(base::MessageLoop::TaskObserver
* task_observer
) override
;
55 void RemoveTaskObserver(
56 base::MessageLoop::TaskObserver
* task_observer
) override
;
57 void Shutdown() override
;
58 void SuspendTimerQueue() override
;
59 void ResumeTimerQueue() override
;
61 SchedulerHelper
* GetSchedulerHelperForTesting();
62 base::TimeTicks
CurrentIdleTaskDeadlineForTesting() const;
65 friend class RendererSchedulerImplTest
;
66 friend class RendererSchedulerImplForTest
;
68 // Keep RendererSchedulerImpl::PolicyToString in sync with this enum.
72 COMPOSITOR_CRITICAL_PATH_PRIORITY
,
75 // Must be the last entry.
77 FIRST_POLICY
= NORMAL
,
80 class PollableNeedsUpdateFlag
{
82 PollableNeedsUpdateFlag(base::Lock
* write_lock
);
83 ~PollableNeedsUpdateFlag();
85 // Set the flag. May only be called if |write_lock| is held.
86 void SetWhileLocked(bool value
);
88 // Returns true iff the flag is set to true.
92 base::subtle::Atomic32 flag_
;
93 base::Lock
* write_lock_
; // Not owned.
95 DISALLOW_COPY_AND_ASSIGN(PollableNeedsUpdateFlag
);
98 // IdleHelper::Delegate implementation:
99 bool CanEnterLongIdlePeriod(
101 base::TimeDelta
* next_long_idle_period_delay_out
) override
;
102 void IsNotQuiescent() override
{}
103 void OnIdlePeriodStarted() override
;
104 void OnIdlePeriodEnded() override
;
106 void EndIdlePeriod();
108 // Returns the serialized scheduler state for tracing.
109 scoped_refptr
<base::trace_event::ConvertableToTraceFormat
> AsValue(
110 base::TimeTicks optional_now
) const;
111 scoped_refptr
<base::trace_event::ConvertableToTraceFormat
> AsValueLocked(
112 base::TimeTicks optional_now
) const;
113 static const char* PolicyToString(Policy policy
);
115 static bool ShouldPrioritizeInputEvent(
116 const blink::WebInputEvent
& web_input_event
);
118 // The time we should stay in a priority-escalated mode after an input event.
119 static const int kPriorityEscalationAfterInputMillis
= 100;
121 // The amount of time which idle periods can continue being scheduled when the
122 // renderer has been hidden, before going to sleep for good.
123 static const int kEndIdleWhenHiddenDelayMillis
= 10000;
125 // The amount of time for which loading tasks will be prioritized over
126 // other tasks during the initial page load.
127 static const int kRailsInitialLoadingPrioritizationMillis
= 1000;
129 // For the purposes of deciding whether or not it's safe to turn timers and
130 // loading tasks on only in idle periods, we regard the system as being as
131 // being "idle period" starved if there hasn't been an idle period in the last
132 // 10 seconds. This was chosen to be long enough to cover most anticipated
134 static const int kIdlePeriodStarvationThresholdMillis
= 10000;
136 // Schedules an immediate PolicyUpdate, if there isn't one already pending and
137 // sets |policy_may_need_update_|. Note |any_thread_lock_| must be
139 void EnsureUrgentPolicyUpdatePostedOnMainThread(
140 const tracked_objects::Location
& from_here
);
142 // Update the policy if a new signal has arrived. Must be called from the main
144 void MaybeUpdatePolicy();
146 // Locks |any_thread_lock_| and updates the scheduler policy. May early
147 // out if the policy is unchanged. Must be called from the main thread.
150 // Like UpdatePolicy, except it doesn't early out.
151 void ForceUpdatePolicy();
153 enum class UpdateType
{
154 MAY_EARLY_OUT_IF_POLICY_UNCHANGED
,
158 // The implelemtation of UpdatePolicy & ForceUpdatePolicy. It is allowed to
159 // early out if |update_type| is MAY_EARLY_OUT_IF_POLICY_UNCHANGED.
160 virtual void UpdatePolicyLocked(UpdateType update_type
);
162 // Returns the amount of time left in the current input escalated priority
163 // policy. Can be called from any thread.
164 base::TimeDelta
TimeLeftInInputEscalatedPolicy(base::TimeTicks now
) const;
166 // Helper for computing the new policy. |new_policy_duration| will be filled
167 // with the amount of time after which the policy should be updated again. If
168 // the duration is zero, a new policy update will not be scheduled. Must be
169 // called with |any_thread_lock_| held. Can be called from any thread.
170 Policy
ComputeNewPolicy(base::TimeTicks now
,
171 base::TimeDelta
* new_policy_duration
) const;
173 // Works out if compositor tasks would be prioritized based on the current
174 // input signals. Can be called from any thread.
175 bool InputSignalsSuggestCompositorPriority(base::TimeTicks now
) const;
177 // An input event of some sort happened, the policy may need updating.
178 void UpdateForInputEventOnCompositorThread(blink::WebInputEvent::Type type
,
179 InputEventState input_event_state
);
181 // Returns true if there has been at least one idle period in the last
182 // |kIdlePeriodStarvationThresholdMillis|.
183 bool HadAnIdlePeriodRecently(base::TimeTicks now
) const;
185 SchedulerHelper helper_
;
186 IdleHelper idle_helper_
;
188 const scoped_refptr
<TaskQueue
> control_task_runner_
;
189 const scoped_refptr
<TaskQueue
> compositor_task_runner_
;
190 const scoped_refptr
<TaskQueue
> loading_task_runner_
;
191 const scoped_refptr
<TaskQueue
> timer_task_runner_
;
193 base::Closure update_policy_closure_
;
194 DeadlineTaskRunner delayed_update_policy_runner_
;
195 CancelableClosureHolder end_renderer_hidden_idle_period_closure_
;
197 // We have decided to improve thread safety at the cost of some boilerplate
198 // (the accessors) for the following data members.
200 struct MainThreadOnly
{
204 TaskCostEstimator timer_task_cost_estimator_
;
205 cc::RollingTimeDeltaHistory short_idle_period_duration_
;
206 Policy current_policy_
;
207 base::TimeTicks current_policy_expiration_time_
;
208 base::TimeTicks estimated_next_frame_begin_
;
209 base::TimeDelta expected_short_idle_period_duration_
;
210 int timer_queue_suspend_count_
; // TIMER_TASK_QUEUE suspended if non-zero.
211 bool renderer_hidden_
;
218 base::TimeTicks last_input_signal_time_
;
219 base::TimeTicks last_idle_period_end_time_
;
220 base::TimeTicks rails_loading_priority_deadline_
;
221 int pending_main_thread_input_event_count_
;
222 bool awaiting_touch_start_response_
;
223 bool in_idle_period_
;
224 bool begin_main_frame_on_critical_path_
;
225 bool timer_tasks_seem_expensive_
;
228 struct CompositorThreadOnly
{
229 CompositorThreadOnly();
230 ~CompositorThreadOnly();
232 blink::WebInputEvent::Type last_input_type_
;
233 scoped_ptr
<base::ThreadChecker
> compositor_thread_checker_
;
235 void CheckOnValidThread() {
237 // We don't actually care which thread this called from, just so long as
239 if (!compositor_thread_checker_
)
240 compositor_thread_checker_
.reset(new base::ThreadChecker());
241 DCHECK(compositor_thread_checker_
->CalledOnValidThread());
246 // Don't access main_thread_only_, instead use MainThreadOnly().
247 MainThreadOnly main_thread_only_
;
248 MainThreadOnly
& MainThreadOnly() {
249 helper_
.CheckOnValidThread();
250 return main_thread_only_
;
252 const struct MainThreadOnly
& MainThreadOnly() const {
253 helper_
.CheckOnValidThread();
254 return main_thread_only_
;
257 mutable base::Lock any_thread_lock_
;
258 // Don't access any_thread_, instead use AnyThread().
259 AnyThread any_thread_
;
260 AnyThread
& AnyThread() {
261 any_thread_lock_
.AssertAcquired();
264 const struct AnyThread
& AnyThread() const {
265 any_thread_lock_
.AssertAcquired();
269 // Don't access compositor_thread_only_, instead use CompositorThreadOnly().
270 CompositorThreadOnly compositor_thread_only_
;
271 CompositorThreadOnly
& CompositorThreadOnly() {
272 compositor_thread_only_
.CheckOnValidThread();
273 return compositor_thread_only_
;
276 PollableThreadSafeFlag policy_may_need_update_
;
277 base::WeakPtrFactory
<RendererSchedulerImpl
> weak_factory_
;
279 DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImpl
);
282 } // namespace scheduler
284 #endif // COMPONENTS_SCHEDULER_RENDERER_RENDERER_SCHEDULER_IMPL_H_