1 // Copyright 2015 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_CHILD_IDLE_HELPER_H_
6 #define COMPONENTS_SCHEDULER_CHILD_IDLE_HELPER_H_
8 #include "base/message_loop/message_loop.h"
9 #include "components/scheduler/child/cancelable_closure_holder.h"
10 #include "components/scheduler/child/prioritizing_task_queue_selector.h"
11 #include "components/scheduler/child/scheduler_helper.h"
12 #include "components/scheduler/child/single_thread_idle_task_runner.h"
13 #include "components/scheduler/scheduler_export.h"
17 class SchedulerHelper
;
19 // Common scheduler functionality for Idle tasks.
20 class SCHEDULER_EXPORT IdleHelper
21 : public base::MessageLoop::TaskObserver
,
22 public SingleThreadIdleTaskRunner::Delegate
{
24 // Used to by scheduler implementations to customize idle behaviour.
25 class SCHEDULER_EXPORT Delegate
{
30 // If it's ok to enter a long idle period, return true. Otherwise return
31 // false and set next_long_idle_period_delay_out so we know when to try
33 virtual bool CanEnterLongIdlePeriod(
35 base::TimeDelta
* next_long_idle_period_delay_out
) = 0;
37 // Signals that the Long Idle Period hasn't started yet because the system
39 virtual void IsNotQuiescent() = 0;
41 // Signals that we have started an Idle Period.
42 virtual void OnIdlePeriodStarted() = 0;
44 // Signals that we have finished an Idle Period.
45 virtual void OnIdlePeriodEnded() = 0;
48 DISALLOW_COPY_AND_ASSIGN(Delegate
);
51 // Keep IdleHelper::IdlePeriodStateToString in sync with this enum.
52 enum class IdlePeriodState
{
56 IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE
,
57 IN_LONG_IDLE_PERIOD_PAUSED
,
58 // Must be the last entry.
59 IDLE_PERIOD_STATE_COUNT
,
60 FIRST_IDLE_PERIOD_STATE
= NOT_IN_IDLE_PERIOD
,
63 // The maximum length of an idle period.
64 static const int kMaximumIdlePeriodMillis
= 50;
66 // |helper| and |delegate| are not owned by IdleHelper object and must
69 SchedulerHelper
* helper
,
71 size_t idle_queue_index
,
72 const char* tracing_category
,
73 const char* disabled_by_default_tracing_category
,
74 const char* idle_period_tracing_name
,
75 base::TimeDelta required_quiescence_duration_before_long_idle_period
);
76 ~IdleHelper() override
;
78 // Returns the idle task runner. Tasks posted to this runner may be reordered
79 // relative to other task types and may be starved for an arbitrarily long
80 // time if no idle time is available.
81 scoped_refptr
<SingleThreadIdleTaskRunner
> IdleTaskRunner();
83 // If |required_quiescence_duration_before_long_idle_period_| is zero then
84 // immediately initiate a long idle period, otherwise check if any tasks have
85 // run recently and if so, check again after a delay of
86 // |required_quiescence_duration_before_long_idle_period_|.
87 // Calling this function will end any previous idle period immediately, and
88 // potentially again later if
89 // |required_quiescence_duration_before_long_idle_period_| is non-zero.
90 // NOTE EndIdlePeriod will disable the long idle periods.
91 void EnableLongIdlePeriod();
93 // Start an idle period with a given idle period deadline.
94 void StartIdlePeriod(IdlePeriodState new_idle_period_state
,
96 base::TimeTicks idle_period_deadline
);
98 // This will end an idle period either started with StartIdlePeriod or
99 // EnableLongIdlePeriod.
100 void EndIdlePeriod();
102 // Returns true if a currently running idle task could exceed its deadline
103 // without impacting user experience too much. This should only be used if
104 // there is a task which cannot be pre-empted and is likely to take longer
105 // than the largest expected idle task deadline. It should NOT be polled to
106 // check whether more work can be performed on the current idle task after
107 // its deadline has expired - post a new idle task for the continuation of the
108 // work in this case.
109 // Must be called from the thread this class was created on.
110 bool CanExceedIdleDeadlineIfRequired() const;
112 // Returns the deadline for the current idle task.
113 base::TimeTicks
CurrentIdleTaskDeadline() const;
115 // SingleThreadIdleTaskRunner::Delegate implementation:
116 void OnIdleTaskPosted() override
;
117 base::TimeTicks
WillProcessIdleTask() override
;
118 void DidProcessIdleTask() override
;
120 // base::MessageLoop::TaskObserver implementation:
121 void WillProcessTask(const base::PendingTask
& pending_task
) override
;
122 void DidProcessTask(const base::PendingTask
& pending_task
) override
;
124 IdlePeriodState
SchedulerIdlePeriodState() const;
125 static const char* IdlePeriodStateToString(IdlePeriodState state
);
128 friend class BaseIdleHelperTest
;
129 friend class IdleHelperTest
;
133 State(SchedulerHelper
* helper
,
135 const char* tracing_category
,
136 const char* disabled_by_default_tracing_category
,
137 const char* idle_period_tracing_name
);
140 void UpdateState(IdlePeriodState new_state
,
141 base::TimeTicks new_deadline
,
142 base::TimeTicks optional_now
);
143 bool IsIdlePeriodPaused() const;
145 IdlePeriodState
idle_period_state() const;
146 base::TimeTicks
idle_period_deadline() const;
148 void TraceIdleIdleTaskStart();
149 void TraceIdleIdleTaskEnd();
150 void TraceEventIdlePeriodStateChange(IdlePeriodState new_state
,
151 base::TimeTicks new_deadline
,
152 base::TimeTicks optional_now
);
155 SchedulerHelper
* helper_
; // NOT OWNED
156 Delegate
* delegate_
; // NOT OWNED
158 IdlePeriodState idle_period_state_
;
159 base::TimeTicks idle_period_deadline_
;
161 base::TraceTicks idle_period_deadline_for_tracing_
;
162 base::TraceTicks last_idle_task_trace_time_
;
163 bool nestable_events_started_
;
164 const char* tracing_category_
;
165 const char* disabled_by_default_tracing_category_
;
166 const char* idle_period_tracing_name_
;
168 DISALLOW_COPY_AND_ASSIGN(State
);
171 // The minimum duration of an idle period.
172 static const int kMinimumIdlePeriodDurationMillis
= 1;
174 // The minimum delay to wait between retrying to initiate a long idle time.
175 static const int kRetryEnableLongIdlePeriodDelayMillis
= 1;
177 // Returns the new idle period state for the next long idle period. Fills in
178 // |next_long_idle_period_delay_out| with the next time we should try to
179 // initiate the next idle period.
180 IdlePeriodState
ComputeNewLongIdlePeriodState(
181 const base::TimeTicks now
,
182 base::TimeDelta
* next_long_idle_period_delay_out
);
184 bool ShouldWaitForQuiescence();
185 void OnIdleTaskPostedOnMainThread();
186 void UpdateLongIdlePeriodStateAfterIdleTask();
188 void SetIdlePeriodState(IdlePeriodState new_state
,
189 base::TimeTicks new_deadline
,
190 base::TimeTicks optional_now
);
192 // Returns true if |state| represents being within an idle period state.
193 static bool IsInIdlePeriod(IdlePeriodState state
);
194 // Returns true if |state| represents being within a long idle period state.
195 static bool IsInLongIdlePeriod(IdlePeriodState state
);
197 SchedulerHelper
* helper_
; // NOT OWNED
198 Delegate
* delegate_
; // NOT OWNED
199 size_t idle_queue_index_
;
200 scoped_refptr
<SingleThreadIdleTaskRunner
> idle_task_runner_
;
202 CancelableClosureHolder enable_next_long_idle_period_closure_
;
203 CancelableClosureHolder on_idle_task_posted_closure_
;
207 // A bitmap which controls the set of queues that are checked for quiescence
208 // before triggering a long idle period.
209 uint64 quiescence_monitored_task_queue_mask_
;
210 base::TimeDelta required_quiescence_duration_before_long_idle_period_
;
212 const char* disabled_by_default_tracing_category_
;
214 base::WeakPtr
<IdleHelper
> weak_idle_helper_ptr_
;
215 base::WeakPtrFactory
<IdleHelper
> weak_factory_
;
217 DISALLOW_COPY_AND_ASSIGN(IdleHelper
);
220 } // namespace scheduler
222 #endif // COMPONENTS_SCHEDULER_CHILD_IDLE_HELPER_H_