OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #ifndef CONTENT_CHILD_SCHEDULER_SCHEDULER_HELPER_H_ | |
6 #define CONTENT_CHILD_SCHEDULER_SCHEDULER_HELPER_H_ | |
7 | |
8 #include "content/child/scheduler/cancelable_closure_holder.h" | |
9 #include "content/child/scheduler/single_thread_idle_task_runner.h" | |
10 #include "content/child/scheduler/task_queue_manager.h" | |
11 #include "content/child/scheduler/time_source.h" | |
12 | |
13 namespace content { | |
14 | |
15 class PrioritizingTaskQueueSelector; | |
16 class NestableSingleThreadTaskRunner; | |
17 | |
18 // Common scheduler functionality for Default and Idle tasks. | |
19 class CONTENT_EXPORT SchedulerHelper { | |
20 public: | |
21 // Used to by scheduler implementations to customize idle behaviour. | |
22 class CONTENT_EXPORT SchedulerHelperDelegate { | |
23 public: | |
24 SchedulerHelperDelegate(); | |
25 virtual ~SchedulerHelperDelegate(); | |
26 | |
27 // If it's ok to enter a Long Idle period, return true. Otherwise return | |
28 // false and set next_long_idle_period_delay_out so we know when to try | |
29 // again. | |
30 virtual bool CanEnterLongIdlePeriod( | |
31 base::TimeTicks now, | |
32 base::TimeDelta* next_long_idle_period_delay_out) = 0; | |
33 | |
34 // Signals that the Long Idle Period hasn't started yet because the system | |
35 // isn't quiescent. | |
36 virtual void IsNotQuiescent() = 0; | |
37 | |
38 private: | |
39 DISALLOW_COPY_AND_ASSIGN(SchedulerHelperDelegate); | |
40 }; | |
41 | |
42 // NOTE |total_task_queue_count| must be >= TASK_QUEUE_COUNT. | |
43 // Category strings must have application lifetime (statics or | |
44 // literals). They may not include " chars. | |
45 SchedulerHelper( | |
46 scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner, | |
47 SchedulerHelperDelegate* scheduler_helper_delegate, | |
48 const char* tracing_category, | |
49 const char* disabled_by_default_tracing_category, | |
50 const char* idle_period_tracing_name, | |
51 size_t total_task_queue_count, | |
52 base::TimeDelta required_quiescence_duration_before_long_idle_period); | |
53 ~SchedulerHelper(); | |
54 | |
55 // Returns the default task runner. | |
56 scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner(); | |
57 | |
58 // Returns the idle task runner. Tasks posted to this runner may be reordered | |
59 // relative to other task types and may be starved for an arbitrarily long | |
60 // time if no idle time is available. | |
61 scoped_refptr<SingleThreadIdleTaskRunner> IdleTaskRunner(); | |
62 | |
63 // Returns the control task runner. Tasks posted to this runner are executed | |
64 // with the highest priority. Care must be taken to avoid starvation of other | |
65 // task queues. | |
66 scoped_refptr<base::SingleThreadTaskRunner> ControlTaskRunner(); | |
67 | |
68 // Returns true if a currently running idle task could exceed its deadline | |
69 // without impacting user experience too much. This should only be used if | |
70 // there is a task which cannot be pre-empted and is likely to take longer | |
71 // than the largest expected idle task deadline. It should NOT be polled to | |
72 // check whether more work can be performed on the current idle task after | |
73 // its deadline has expired - post a new idle task for the continuation of the | |
74 // work in this case. | |
75 // Must be called from the thread this class was created on. | |
76 bool CanExceedIdleDeadlineIfRequired() const; | |
77 | |
78 // Adds or removes a task observer from the scheduler. The observer will be | |
79 // notified before and after every executed task. These functions can only be | |
80 // called on the thread this class was created on. | |
81 void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer); | |
82 void RemoveTaskObserver(base::MessageLoop::TaskObserver* task_observer); | |
83 | |
84 // Shuts down the scheduler by dropping any remaining pending work in the work | |
85 // queues. After this call any work posted to the task runners will be | |
86 // silently dropped. | |
87 void Shutdown(); | |
88 | |
89 // Returns true if Shutdown() has been called. Otherwise returns false. | |
90 bool IsShutdown() const { return !task_queue_manager_.get(); } | |
91 | |
92 // Keep SchedulerHelper::TaskQueueIdToString in sync with this enum. | |
93 enum QueueId { | |
94 DEFAULT_TASK_QUEUE, | |
95 IDLE_TASK_QUEUE, | |
96 CONTROL_TASK_QUEUE, | |
97 CONTROL_TASK_AFTER_WAKEUP_QUEUE, | |
98 // Must be the last entry. | |
99 TASK_QUEUE_COUNT, | |
100 }; | |
101 | |
102 // Keep SchedulerHelper::IdlePeriodStateToString in sync with this enum. | |
103 enum class IdlePeriodState { | |
104 NOT_IN_IDLE_PERIOD, | |
105 IN_SHORT_IDLE_PERIOD, | |
106 IN_LONG_IDLE_PERIOD, | |
107 IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE, | |
108 ENDING_LONG_IDLE_PERIOD | |
109 }; | |
110 | |
111 static const char* TaskQueueIdToString(QueueId queue_id); | |
112 static const char* IdlePeriodStateToString(IdlePeriodState state); | |
113 | |
114 // The maximum length of an idle period. | |
115 static const int kMaximumIdlePeriodMillis = 50; | |
116 | |
117 // The minimum delay to wait between retrying to initiate a long idle time. | |
118 static const int kRetryEnableLongIdlePeriodDelayMillis = 1; | |
119 | |
120 // IdleTaskDeadlineSupplier Implementation: | |
121 void CurrentIdleTaskDeadlineCallback(base::TimeTicks* deadline_out) const; | |
122 | |
123 // Returns the new idle period state for the next long idle period. Fills in | |
124 // |next_long_idle_period_delay_out| with the next time we should try to | |
125 // initiate the next idle period. | |
126 IdlePeriodState ComputeNewLongIdlePeriodState( | |
127 const base::TimeTicks now, | |
128 base::TimeDelta* next_long_idle_period_delay_out); | |
129 | |
130 // If |required_quiescence_duration_before_long_idle_period_| is zero then | |
131 // immediately initiate a long idle period, otherwise check if any tasks have | |
132 // run recently and if so, check again after a delay of | |
133 // |required_quiescence_duration_before_long_idle_period_|. | |
134 // Calling this function will end any previous idle period immediately, and | |
135 // potentially again later if | |
136 // |required_quiescence_duration_before_long_idle_period_| is non-zero. | |
137 // NOTE EndIdlePeriod will disable the long idle periods. | |
138 void EnableLongIdlePeriod(); | |
139 | |
140 // Start and end an idle period. If |post_end_idle_period| is true, it will | |
141 // post a delayed EndIdlePeriod scheduled to occur at |idle_period_deadline|. | |
142 void StartIdlePeriod(IdlePeriodState new_idle_period_state, | |
143 base::TimeTicks now, | |
144 base::TimeTicks idle_period_deadline, | |
145 bool post_end_idle_period); | |
146 | |
147 // This will end an idle period either started with StartIdlePeriod or | |
148 // EnableLongIdlePeriod. | |
149 void EndIdlePeriod(); | |
150 | |
151 // Returns true if |state| represents being within an idle period state. | |
152 static bool IsInIdlePeriod(IdlePeriodState state); | |
153 | |
154 void CheckOnValidThread() const { | |
155 DCHECK(thread_checker_.CalledOnValidThread()); | |
156 } | |
157 | |
158 // Accessor methods. | |
159 base::TimeTicks Now() const; | |
160 IdlePeriodState SchedulerIdlePeriodState() const; | |
161 PrioritizingTaskQueueSelector* SchedulerTaskQueueSelector() const; | |
162 scoped_refptr<base::SingleThreadTaskRunner> TaskRunnerForQueue( | |
163 size_t queue_index) const; | |
164 void SetQueueName(size_t queue_index, const char* name); | |
165 bool IsQueueEmpty(size_t queue_index) const; | |
166 | |
167 // Test helpers. | |
168 void SetTimeSourceForTesting(scoped_ptr<TimeSource> time_source); | |
169 void SetWorkBatchSizeForTesting(size_t work_batch_size); | |
170 TaskQueueManager* GetTaskQueueManagerForTesting(); | |
171 | |
172 private: | |
173 friend class SchedulerHelperTest; | |
174 | |
175 bool ShouldWaitForQuiescence(); | |
176 void EnableLongIdlePeriodAfterWakeup(); | |
177 | |
178 base::ThreadChecker thread_checker_; | |
179 scoped_ptr<PrioritizingTaskQueueSelector> task_queue_selector_; | |
180 scoped_ptr<TaskQueueManager> task_queue_manager_; | |
181 | |
182 CancelableClosureHolder end_idle_period_closure_; | |
183 CancelableClosureHolder enable_next_long_idle_period_closure_; | |
184 CancelableClosureHolder enable_next_long_idle_period_after_wakeup_closure_; | |
185 | |
186 IdlePeriodState idle_period_state_; | |
187 SchedulerHelperDelegate* scheduler_helper_delegate_; // NOT OWNED | |
188 | |
189 scoped_refptr<base::SingleThreadTaskRunner> control_task_runner_; | |
190 scoped_refptr<base::SingleThreadTaskRunner> control_task_after_wakeup_runner_; | |
191 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; | |
192 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_; | |
193 | |
194 // A bitmap which controls the set of queues that are checked for quiescence | |
195 // before triggering a long idle period. | |
196 uint64 quiescence_monitored_task_queue_mask_; | |
197 base::TimeDelta required_quiescence_duration_before_long_idle_period_; | |
198 | |
199 base::TimeTicks idle_period_deadline_; | |
200 scoped_ptr<TimeSource> time_source_; | |
201 | |
202 const char* tracing_category_; | |
203 const char* disabled_by_default_tracing_category_; | |
204 const char* idle_period_tracing_name_; | |
205 | |
206 base::WeakPtr<SchedulerHelper> weak_scheduler_ptr_; | |
207 base::WeakPtrFactory<SchedulerHelper> weak_factory_; | |
208 | |
209 DISALLOW_COPY_AND_ASSIGN(SchedulerHelper); | |
210 }; | |
211 | |
212 } // namespace content | |
213 | |
214 #endif // CONTENT_CHILD_SCHEDULER_SCHEDULER_HELPER_H_ | |
OLD | NEW |