Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / scheduler / renderer / renderer_scheduler_impl.h
blobbd7d7ad7e978d97e032e7751613f10c61014cf15
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"
19 namespace base {
20 namespace trace_event {
21 class ConvertableToTraceFormat;
25 namespace scheduler {
27 class SCHEDULER_EXPORT RendererSchedulerImpl : public RendererScheduler,
28 public IdleHelper::Delegate {
29 public:
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;
65 // Test helpers.
66 SchedulerHelper* GetSchedulerHelperForTesting();
67 TaskCostEstimator* GetLoadingTaskCostEstimatorForTesting();
68 TaskCostEstimator* GetTimerTaskCostEstimatorForTesting();
69 base::TimeTicks CurrentIdleTaskDeadlineForTesting() const;
71 private:
72 friend class RendererSchedulerImplTest;
73 friend class RendererSchedulerImplForTest;
75 struct Policy {
76 Policy();
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 {
92 public:
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.
100 bool IsSet() const;
102 private:
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(
111 base::TimeTicks now,
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
140 // user gestures.
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
150 // locked.
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
155 // thread.
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.
160 void UpdatePolicy();
162 // Like UpdatePolicy, except it doesn't early out.
163 void ForceUpdatePolicy();
165 enum class UpdateType {
166 MAY_EARLY_OUT_IF_POLICY_UNCHANGED,
167 FORCE_UPDATE,
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
178 // any thread.
179 UseCase ComputeCurrentUseCase(
180 base::TimeTicks now,
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 {
221 MainThreadOnly();
222 ~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;
237 bool was_shutdown;
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;
244 struct AnyThread {
245 AnyThread();
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;
251 bool in_idle_period;
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() {
263 #if DCHECK_IS_ON()
264 // We don't actually care which thread this called from, just so long as
265 // its consistent.
266 if (!compositor_thread_checker)
267 compositor_thread_checker.reset(new base::ThreadChecker());
268 DCHECK(compositor_thread_checker->CalledOnValidThread());
269 #endif
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();
289 return any_thread_;
291 const struct AnyThread& AnyThread() const {
292 any_thread_lock_.AssertAcquired();
293 return any_thread_;
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_