OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/task_scheduler/task_scheduler_impl.h" | 5 #include "base/task_scheduler/task_scheduler_impl.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
47 size_t GetEnvironmentIndexForTraits(const TaskTraits& traits) { | 47 size_t GetEnvironmentIndexForTraits(const TaskTraits& traits) { |
48 const bool is_background = | 48 const bool is_background = |
49 traits.priority() == base::TaskPriority::BACKGROUND; | 49 traits.priority() == base::TaskPriority::BACKGROUND; |
50 if (traits.may_block() || traits.with_base_sync_primitives()) | 50 if (traits.may_block() || traits.with_base_sync_primitives()) |
51 return is_background ? BACKGROUND_BLOCKING : FOREGROUND_BLOCKING; | 51 return is_background ? BACKGROUND_BLOCKING : FOREGROUND_BLOCKING; |
52 return is_background ? BACKGROUND : FOREGROUND; | 52 return is_background ? BACKGROUND : FOREGROUND; |
53 } | 53 } |
54 | 54 |
55 } // namespace | 55 } // namespace |
56 | 56 |
57 // static | 57 TaskSchedulerImpl::TaskSchedulerImpl(StringPiece name) |
58 std::unique_ptr<TaskSchedulerImpl> TaskSchedulerImpl::Create( | 58 : name_(name), |
59 StringPiece name, | 59 service_thread_("TaskSchedulerServiceThread"), |
60 const TaskScheduler::InitParams& init_params) { | 60 single_thread_task_runner_manager_(&task_tracker_, |
61 auto task_scheduler = WrapUnique(new TaskSchedulerImpl(name)); | 61 &delayed_task_manager_) { |
62 task_scheduler->Initialize(init_params); | 62 static_assert(arraysize(worker_pools_) == ENVIRONMENT_COUNT, |
63 return task_scheduler; | 63 "The size of |worker_pools_| must match ENVIRONMENT_COUNT."); |
64 static_assert( | |
65 arraysize(kEnvironmentParams) == ENVIRONMENT_COUNT, | |
66 "The size of |kEnvironmentParams| must match ENVIRONMENT_COUNT."); | |
67 | |
68 for (int environment_type = 0; environment_type < ENVIRONMENT_COUNT; | |
69 ++environment_type) { | |
70 worker_pools_[environment_type] = MakeUnique<SchedulerWorkerPoolImpl>( | |
71 name_ + kEnvironmentParams[environment_type].name_suffix, | |
72 kEnvironmentParams[environment_type].priority_hint, | |
73 Bind(&TaskSchedulerImpl::ReEnqueueSequenceCallback, Unretained(this)), | |
gab
2017/04/25 15:16:15
Note for https://codereview.chromium.org/280706300
fdoray
2017/04/25 18:43:34
Done.
| |
74 &task_tracker_, &delayed_task_manager_); | |
75 } | |
64 } | 76 } |
65 | 77 |
66 TaskSchedulerImpl::~TaskSchedulerImpl() { | 78 TaskSchedulerImpl::~TaskSchedulerImpl() { |
67 #if DCHECK_IS_ON() | 79 #if DCHECK_IS_ON() |
68 DCHECK(join_for_testing_returned_.IsSet()); | 80 DCHECK(join_for_testing_returned_.IsSet()); |
69 #endif | 81 #endif |
70 } | 82 } |
71 | 83 |
84 void TaskSchedulerImpl::Start(const TaskScheduler::InitParams& init_params) { | |
85 // Start the service thread. On platforms that support it (POSIX except NaCL | |
86 // SFI), the service thread runs a MessageLoopForIO which is used to support | |
87 // FileDescriptorWatcher in the scope in which tasks run. | |
88 Thread::Options service_thread_options; | |
89 service_thread_options.message_loop_type = | |
90 #if defined(OS_POSIX) && !defined(OS_NACL_SFI) | |
91 MessageLoop::TYPE_IO; | |
92 #else | |
93 MessageLoop::TYPE_DEFAULT; | |
94 #endif | |
95 service_thread_options.timer_slack = TIMER_SLACK_MAXIMUM; | |
96 CHECK(service_thread_.StartWithOptions(service_thread_options)); | |
97 | |
98 #if defined(OS_POSIX) && !defined(OS_NACL_SFI) | |
99 // Needs to happen after starting the service thread to get its | |
100 // message_loop(). | |
101 task_tracker_.set_watch_file_descriptor_message_loop( | |
102 static_cast<MessageLoopForIO*>(service_thread_.message_loop())); | |
103 #endif | |
104 | |
105 // Needs to happen after starting the service thread to get its task_runner(). | |
106 delayed_task_manager_.Start(service_thread_.task_runner()); | |
107 | |
108 single_thread_task_runner_manager_.Start(); | |
109 | |
110 worker_pools_[BACKGROUND]->Start(init_params.background_worker_pool_params); | |
111 worker_pools_[BACKGROUND_BLOCKING]->Start( | |
112 init_params.background_blocking_worker_pool_params); | |
113 worker_pools_[FOREGROUND]->Start(init_params.foreground_worker_pool_params); | |
114 worker_pools_[FOREGROUND_BLOCKING]->Start( | |
115 init_params.foreground_blocking_worker_pool_params); | |
116 } | |
117 | |
72 void TaskSchedulerImpl::PostDelayedTaskWithTraits( | 118 void TaskSchedulerImpl::PostDelayedTaskWithTraits( |
73 const tracked_objects::Location& from_here, | 119 const tracked_objects::Location& from_here, |
74 const TaskTraits& traits, | 120 const TaskTraits& traits, |
75 OnceClosure task, | 121 OnceClosure task, |
76 TimeDelta delay) { | 122 TimeDelta delay) { |
77 // Post |task| as part of a one-off single-task Sequence. | 123 // Post |task| as part of a one-off single-task Sequence. |
78 GetWorkerPoolForTraits(traits)->PostTaskWithSequence( | 124 GetWorkerPoolForTraits(traits)->PostTaskWithSequence( |
79 MakeUnique<Task>(from_here, std::move(task), traits, delay), | 125 MakeUnique<Task>(from_here, std::move(task), traits, delay), |
80 make_scoped_refptr(new Sequence)); | 126 make_scoped_refptr(new Sequence)); |
81 } | 127 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
143 for (const auto& worker_pool : worker_pools_) | 189 for (const auto& worker_pool : worker_pools_) |
144 worker_pool->DisallowWorkerDetachmentForTesting(); | 190 worker_pool->DisallowWorkerDetachmentForTesting(); |
145 for (const auto& worker_pool : worker_pools_) | 191 for (const auto& worker_pool : worker_pools_) |
146 worker_pool->JoinForTesting(); | 192 worker_pool->JoinForTesting(); |
147 service_thread_.Stop(); | 193 service_thread_.Stop(); |
148 #if DCHECK_IS_ON() | 194 #if DCHECK_IS_ON() |
149 join_for_testing_returned_.Set(); | 195 join_for_testing_returned_.Set(); |
150 #endif | 196 #endif |
151 } | 197 } |
152 | 198 |
153 TaskSchedulerImpl::TaskSchedulerImpl(StringPiece name) | |
154 : name_(name), | |
155 service_thread_("TaskSchedulerServiceThread"), | |
156 single_thread_task_runner_manager_(&task_tracker_, | |
157 &delayed_task_manager_) {} | |
158 | |
159 void TaskSchedulerImpl::Initialize( | |
160 const TaskScheduler::InitParams& init_params) { | |
161 // Start the service thread. On platforms that support it (POSIX except NaCL | |
162 // SFI), the service thread runs a MessageLoopForIO which is used to support | |
163 // FileDescriptorWatcher in the scope in which tasks run. | |
164 Thread::Options service_thread_options; | |
165 service_thread_options.message_loop_type = | |
166 #if defined(OS_POSIX) && !defined(OS_NACL_SFI) | |
167 MessageLoop::TYPE_IO; | |
168 #else | |
169 MessageLoop::TYPE_DEFAULT; | |
170 #endif | |
171 service_thread_options.timer_slack = TIMER_SLACK_MAXIMUM; | |
172 CHECK(service_thread_.StartWithOptions(service_thread_options)); | |
173 | |
174 #if defined(OS_POSIX) && !defined(OS_NACL_SFI) | |
175 // Needs to happen after starting the service thread to get its | |
176 // message_loop(). | |
177 task_tracker_.set_watch_file_descriptor_message_loop( | |
178 static_cast<MessageLoopForIO*>(service_thread_.message_loop())); | |
179 #endif | |
180 | |
181 // Needs to happen after starting the service thread to get its task_runner(). | |
182 delayed_task_manager_.Start(service_thread_.task_runner()); | |
183 | |
184 single_thread_task_runner_manager_.Start(); | |
185 | |
186 // Callback invoked by workers to re-enqueue a sequence in the appropriate | |
187 // PriorityQueue. | |
188 const SchedulerWorkerPoolImpl::ReEnqueueSequenceCallback | |
189 re_enqueue_sequence_callback = | |
190 Bind(&TaskSchedulerImpl::ReEnqueueSequenceCallback, Unretained(this)); | |
191 | |
192 // Order must match the EnvironmentType enum. | |
193 const SchedulerWorkerPoolParams* worker_pool_params[] = { | |
194 &init_params.background_worker_pool_params, | |
195 &init_params.background_blocking_worker_pool_params, | |
196 &init_params.foreground_worker_pool_params, | |
197 &init_params.foreground_blocking_worker_pool_params}; | |
198 | |
199 static_assert(arraysize(worker_pools_) == ENVIRONMENT_COUNT, | |
200 "The size of |worker_pools_| must match ENVIRONMENT_COUNT."); | |
201 static_assert( | |
202 arraysize(kEnvironmentParams) == ENVIRONMENT_COUNT, | |
203 "The size of |kEnvironmentParams| must match ENVIRONMENT_COUNT."); | |
204 static_assert( | |
205 arraysize(worker_pool_params) == ENVIRONMENT_COUNT, | |
206 "The size of |worker_pool_params| must match ENVIRONMENT_COUNT."); | |
207 | |
208 // Start worker pools. | |
209 for (int environment_type = 0; environment_type < ENVIRONMENT_COUNT; | |
210 ++environment_type) { | |
211 // Passing pointers to objects owned by |this| to the constructor of | |
212 // SchedulerWorkerPoolImpl is safe because a TaskSchedulerImpl can't be | |
213 // deleted before all its worker pools have been joined. | |
214 worker_pools_[environment_type] = MakeUnique<SchedulerWorkerPoolImpl>( | |
215 name_ + kEnvironmentParams[environment_type].name_suffix, | |
216 kEnvironmentParams[environment_type].priority_hint, | |
217 re_enqueue_sequence_callback, &task_tracker_, &delayed_task_manager_); | |
218 worker_pools_[environment_type]->Start( | |
219 *worker_pool_params[environment_type]); | |
220 } | |
221 } | |
222 | |
223 SchedulerWorkerPoolImpl* TaskSchedulerImpl::GetWorkerPoolForTraits( | 199 SchedulerWorkerPoolImpl* TaskSchedulerImpl::GetWorkerPoolForTraits( |
224 const TaskTraits& traits) const { | 200 const TaskTraits& traits) const { |
225 return worker_pools_[GetEnvironmentIndexForTraits(traits)].get(); | 201 return worker_pools_[GetEnvironmentIndexForTraits(traits)].get(); |
226 } | 202 } |
227 | 203 |
228 void TaskSchedulerImpl::ReEnqueueSequenceCallback( | 204 void TaskSchedulerImpl::ReEnqueueSequenceCallback( |
229 scoped_refptr<Sequence> sequence) { | 205 scoped_refptr<Sequence> sequence) { |
230 DCHECK(sequence); | 206 DCHECK(sequence); |
231 | 207 |
232 const SequenceSortKey sort_key = sequence->GetSortKey(); | 208 const SequenceSortKey sort_key = sequence->GetSortKey(); |
233 | 209 |
234 // The next task in |sequence| should run in a worker pool suited for its | 210 // The next task in |sequence| should run in a worker pool suited for its |
235 // traits, except for the priority which is adjusted to the highest priority | 211 // traits, except for the priority which is adjusted to the highest priority |
236 // in |sequence|. | 212 // in |sequence|. |
237 const TaskTraits traits = | 213 const TaskTraits traits = |
238 sequence->PeekTaskTraits().WithPriority(sort_key.priority()); | 214 sequence->PeekTaskTraits().WithPriority(sort_key.priority()); |
239 | 215 |
240 GetWorkerPoolForTraits(traits)->ReEnqueueSequence(std::move(sequence), | 216 GetWorkerPoolForTraits(traits)->ReEnqueueSequence(std::move(sequence), |
241 sort_key); | 217 sort_key); |
242 } | 218 } |
243 | 219 |
244 } // namespace internal | 220 } // namespace internal |
245 } // namespace base | 221 } // namespace base |
OLD | NEW |