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" |
11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
12 #include "base/task_scheduler/delayed_task_manager.h" | 12 #include "base/task_scheduler/delayed_task_manager.h" |
13 #include "base/task_scheduler/scheduler_single_thread_task_runner_manager.h" | 13 #include "base/task_scheduler/scheduler_single_thread_task_runner_manager.h" |
14 #include "base/task_scheduler/scheduler_worker_pool_params.h" | 14 #include "base/task_scheduler/scheduler_worker_pool_params.h" |
15 #include "base/task_scheduler/sequence_sort_key.h" | 15 #include "base/task_scheduler/sequence_sort_key.h" |
16 #include "base/task_scheduler/task.h" | 16 #include "base/task_scheduler/task.h" |
17 #include "base/task_scheduler/task_tracker.h" | 17 #include "base/task_scheduler/task_tracker.h" |
18 #include "build/build_config.h" | 18 #include "build/build_config.h" |
19 | 19 |
20 #if defined(OS_POSIX) && !defined(OS_NACL_SFI) | 20 #if defined(OS_POSIX) && !defined(OS_NACL_SFI) |
21 #include "base/task_scheduler/task_tracker_posix.h" | 21 #include "base/task_scheduler/task_tracker_posix.h" |
22 #endif | 22 #endif |
23 | 23 |
24 namespace base { | 24 namespace base { |
25 namespace internal { | 25 namespace internal { |
26 | 26 |
| 27 namespace { |
| 28 |
| 29 enum EnvironmentType { |
| 30 BACKGROUND = 0, |
| 31 BACKGROUND_BLOCKING, |
| 32 FOREGROUND, |
| 33 FOREGROUND_BLOCKING, |
| 34 ENVIRONMENT_COUNT // Always last. |
| 35 }; |
| 36 |
| 37 // Order must match the EnvironmentType enum. |
| 38 constexpr struct { |
| 39 // The threads and histograms of this environment will be labeled with |
| 40 // task scheduler name + |name_suffix|. |
| 41 const char* name_suffix; |
| 42 |
| 43 // Preferred priority for threads in this environment; the actual thread |
| 44 // priority depends on shutdown state and platform capabilities. |
| 45 ThreadPriority priority_hint; |
| 46 |
| 47 // Offset of the SchedulerWorkerPoolParams corresponding to this environement |
| 48 // in TaskSchedulerInitParams. |
| 49 size_t offset; |
| 50 } kEnvironmentParams[] = { |
| 51 {"Background", base::ThreadPriority::BACKGROUND, |
| 52 offsetof(TaskSchedulerInitParams, background_worker_pool_params)}, |
| 53 {"BackgroundBlocking", base::ThreadPriority::BACKGROUND, |
| 54 offsetof(TaskSchedulerInitParams, background_blocking_worker_pool_params)}, |
| 55 {"Foreground", base::ThreadPriority::NORMAL, |
| 56 offsetof(TaskSchedulerInitParams, foreground_worker_pool_params)}, |
| 57 {"ForegroundBlocking", base::ThreadPriority::NORMAL, |
| 58 offsetof(TaskSchedulerInitParams, foreground_blocking_worker_pool_params)}, |
| 59 }; |
| 60 |
| 61 size_t GetEnvironmentIndexForTraits(const TaskTraits& traits) { |
| 62 const bool is_background = |
| 63 traits.priority() == base::TaskPriority::BACKGROUND; |
| 64 if (traits.may_block() || traits.with_base_sync_primitives()) |
| 65 return is_background ? BACKGROUND_BLOCKING : FOREGROUND_BLOCKING; |
| 66 return is_background ? BACKGROUND : FOREGROUND; |
| 67 } |
| 68 |
| 69 } // namespace |
| 70 |
27 // static | 71 // static |
28 std::unique_ptr<TaskSchedulerImpl> TaskSchedulerImpl::Create( | 72 std::unique_ptr<TaskSchedulerImpl> TaskSchedulerImpl::Create( |
29 const std::vector<SchedulerWorkerPoolParams>& worker_pool_params_vector, | 73 const std::string& name, |
30 const WorkerPoolIndexForTraitsCallback& | 74 const TaskSchedulerInitParams& init_params) { |
31 worker_pool_index_for_traits_callback) { | 75 std::unique_ptr<TaskSchedulerImpl> scheduler(new TaskSchedulerImpl(name)); |
32 std::unique_ptr<TaskSchedulerImpl> scheduler( | 76 scheduler->Initialize(init_params); |
33 new TaskSchedulerImpl(worker_pool_index_for_traits_callback)); | |
34 scheduler->Initialize(worker_pool_params_vector); | |
35 return scheduler; | 77 return scheduler; |
36 } | 78 } |
37 | 79 |
38 TaskSchedulerImpl::~TaskSchedulerImpl() { | 80 TaskSchedulerImpl::~TaskSchedulerImpl() { |
39 #if DCHECK_IS_ON() | 81 #if DCHECK_IS_ON() |
40 DCHECK(join_for_testing_returned_.IsSet()); | 82 DCHECK(join_for_testing_returned_.IsSet()); |
41 #endif | 83 #endif |
42 } | 84 } |
43 | 85 |
44 void TaskSchedulerImpl::PostDelayedTaskWithTraits( | 86 void TaskSchedulerImpl::PostDelayedTaskWithTraits( |
(...skipping 15 matching lines...) Expand all Loading... |
60 scoped_refptr<SequencedTaskRunner> | 102 scoped_refptr<SequencedTaskRunner> |
61 TaskSchedulerImpl::CreateSequencedTaskRunnerWithTraits( | 103 TaskSchedulerImpl::CreateSequencedTaskRunnerWithTraits( |
62 const TaskTraits& traits) { | 104 const TaskTraits& traits) { |
63 return GetWorkerPoolForTraits(traits)->CreateSequencedTaskRunnerWithTraits( | 105 return GetWorkerPoolForTraits(traits)->CreateSequencedTaskRunnerWithTraits( |
64 traits); | 106 traits); |
65 } | 107 } |
66 | 108 |
67 scoped_refptr<SingleThreadTaskRunner> | 109 scoped_refptr<SingleThreadTaskRunner> |
68 TaskSchedulerImpl::CreateSingleThreadTaskRunnerWithTraits( | 110 TaskSchedulerImpl::CreateSingleThreadTaskRunnerWithTraits( |
69 const TaskTraits& traits) { | 111 const TaskTraits& traits) { |
| 112 const auto& environment = |
| 113 kEnvironmentParams[GetEnvironmentIndexForTraits(traits)]; |
70 return single_thread_task_runner_manager_ | 114 return single_thread_task_runner_manager_ |
71 ->CreateSingleThreadTaskRunnerWithTraits(traits); | 115 ->CreateSingleThreadTaskRunnerWithTraits( |
| 116 name_ + environment.name_suffix, environment.priority_hint, traits); |
72 } | 117 } |
73 | 118 |
74 std::vector<const HistogramBase*> TaskSchedulerImpl::GetHistograms() const { | 119 std::vector<const HistogramBase*> TaskSchedulerImpl::GetHistograms() const { |
75 std::vector<const HistogramBase*> histograms; | 120 std::vector<const HistogramBase*> histograms; |
76 for (const auto& worker_pool : worker_pools_) | 121 for (const auto& worker_pool : worker_pools_) |
77 worker_pool->GetHistograms(&histograms); | 122 worker_pool->GetHistograms(&histograms); |
78 | 123 |
79 return histograms; | 124 return histograms; |
80 } | 125 } |
81 | 126 |
(...skipping 21 matching lines...) Expand all Loading... |
103 for (const auto& worker_pool : worker_pools_) | 148 for (const auto& worker_pool : worker_pools_) |
104 worker_pool->DisallowWorkerDetachmentForTesting(); | 149 worker_pool->DisallowWorkerDetachmentForTesting(); |
105 for (const auto& worker_pool : worker_pools_) | 150 for (const auto& worker_pool : worker_pools_) |
106 worker_pool->JoinForTesting(); | 151 worker_pool->JoinForTesting(); |
107 service_thread_.Stop(); | 152 service_thread_.Stop(); |
108 #if DCHECK_IS_ON() | 153 #if DCHECK_IS_ON() |
109 join_for_testing_returned_.Set(); | 154 join_for_testing_returned_.Set(); |
110 #endif | 155 #endif |
111 } | 156 } |
112 | 157 |
113 TaskSchedulerImpl::TaskSchedulerImpl(const WorkerPoolIndexForTraitsCallback& | 158 TaskSchedulerImpl::TaskSchedulerImpl(const std::string& name) |
114 worker_pool_index_for_traits_callback) | 159 : name_(name), service_thread_("TaskSchedulerServiceThread") { |
115 : service_thread_("TaskSchedulerServiceThread"), | 160 static_assert( |
116 worker_pool_index_for_traits_callback_( | 161 sizeof(TaskSchedulerInitParams) / sizeof(SchedulerWorkerPoolParams) == |
117 worker_pool_index_for_traits_callback) { | 162 ENVIRONMENT_COUNT, |
118 DCHECK(!worker_pool_index_for_traits_callback_.is_null()); | 163 "There must be the same number of elements in " |
| 164 "TaskSchedulerInitParams and EnvironmentType."); |
| 165 static_assert(arraysize(kEnvironmentParams) == ENVIRONMENT_COUNT, |
| 166 "There must be the same number of elements in " |
| 167 "|kEnvironmentParams| and EnvironmentType."); |
| 168 static_assert(arraysize(worker_pools_) == ENVIRONMENT_COUNT, |
| 169 "There must be the same number of elements in |worker_pools_| " |
| 170 "and EnvironmentType."); |
119 } | 171 } |
120 | 172 |
121 void TaskSchedulerImpl::Initialize( | 173 void TaskSchedulerImpl::Initialize(const TaskSchedulerInitParams& init_params) { |
122 const std::vector<SchedulerWorkerPoolParams>& worker_pool_params_vector) { | |
123 DCHECK(!worker_pool_params_vector.empty()); | |
124 | |
125 // Start the service thread. On platforms that support it (POSIX except NaCL | 174 // Start the service thread. On platforms that support it (POSIX except NaCL |
126 // SFI), the service thread runs a MessageLoopForIO which is used to support | 175 // SFI), the service thread runs a MessageLoopForIO which is used to support |
127 // FileDescriptorWatcher in the scope in which tasks run. | 176 // FileDescriptorWatcher in the scope in which tasks run. |
128 Thread::Options service_thread_options; | 177 Thread::Options service_thread_options; |
129 service_thread_options.message_loop_type = | 178 service_thread_options.message_loop_type = |
130 #if defined(OS_POSIX) && !defined(OS_NACL_SFI) | 179 #if defined(OS_POSIX) && !defined(OS_NACL_SFI) |
131 MessageLoop::TYPE_IO; | 180 MessageLoop::TYPE_IO; |
132 #else | 181 #else |
133 MessageLoop::TYPE_DEFAULT; | 182 MessageLoop::TYPE_DEFAULT; |
134 #endif | 183 #endif |
(...skipping 10 matching lines...) Expand all Loading... |
145 base::MakeUnique<TaskTracker>(); | 194 base::MakeUnique<TaskTracker>(); |
146 #endif | 195 #endif |
147 | 196 |
148 // Instantiate DelayedTaskManager. Needs to happen after starting the service | 197 // Instantiate DelayedTaskManager. Needs to happen after starting the service |
149 // thread to get its task_runner(). | 198 // thread to get its task_runner(). |
150 delayed_task_manager_ = | 199 delayed_task_manager_ = |
151 base::MakeUnique<DelayedTaskManager>(service_thread_.task_runner()); | 200 base::MakeUnique<DelayedTaskManager>(service_thread_.task_runner()); |
152 | 201 |
153 single_thread_task_runner_manager_ = | 202 single_thread_task_runner_manager_ = |
154 MakeUnique<SchedulerSingleThreadTaskRunnerManager>( | 203 MakeUnique<SchedulerSingleThreadTaskRunnerManager>( |
155 worker_pool_params_vector, worker_pool_index_for_traits_callback_, | |
156 task_tracker_.get(), delayed_task_manager_.get()); | 204 task_tracker_.get(), delayed_task_manager_.get()); |
157 | 205 |
158 // Callback invoked by workers to re-enqueue a sequence in the appropriate | 206 // Callback invoked by workers to re-enqueue a sequence in the appropriate |
159 // PriorityQueue. | 207 // PriorityQueue. |
160 const SchedulerWorkerPoolImpl::ReEnqueueSequenceCallback | 208 const SchedulerWorkerPoolImpl::ReEnqueueSequenceCallback |
161 re_enqueue_sequence_callback = | 209 re_enqueue_sequence_callback = |
162 Bind(&TaskSchedulerImpl::ReEnqueueSequenceCallback, Unretained(this)); | 210 Bind(&TaskSchedulerImpl::ReEnqueueSequenceCallback, Unretained(this)); |
163 | 211 |
164 // Start worker pools. | 212 // Start worker pools. |
165 for (const auto& worker_pool_params : worker_pool_params_vector) { | 213 for (size_t index = 0; index < ENVIRONMENT_COUNT; ++index) { |
166 // Passing pointers to objects owned by |this| to | 214 // Passing pointers to objects owned by |this| to |
167 // SchedulerWorkerPoolImpl::Create() is safe because a TaskSchedulerImpl | 215 // SchedulerWorkerPoolImpl::Create() is safe because a TaskSchedulerImpl |
168 // can't be deleted before all its worker pools have been joined. | 216 // can't be deleted before all its worker pools have been joined. |
169 worker_pools_.push_back(SchedulerWorkerPoolImpl::Create( | 217 worker_pools_[index] = SchedulerWorkerPoolImpl::Create( |
170 worker_pool_params, re_enqueue_sequence_callback, task_tracker_.get(), | 218 name_ + kEnvironmentParams[index].name_suffix, |
171 delayed_task_manager_.get())); | 219 kEnvironmentParams[index].priority_hint, |
172 CHECK(worker_pools_.back()); | 220 *reinterpret_cast<const SchedulerWorkerPoolParams*>( |
| 221 reinterpret_cast<const char*>(&init_params) + |
| 222 kEnvironmentParams[index].offset), |
| 223 re_enqueue_sequence_callback, task_tracker_.get(), |
| 224 delayed_task_manager_.get()); |
| 225 CHECK(worker_pools_[index]); |
173 } | 226 } |
174 } | 227 } |
175 | 228 |
176 SchedulerWorkerPoolImpl* TaskSchedulerImpl::GetWorkerPoolForTraits( | 229 SchedulerWorkerPoolImpl* TaskSchedulerImpl::GetWorkerPoolForTraits( |
177 const TaskTraits& traits) const { | 230 const TaskTraits& traits) const { |
178 const size_t index = worker_pool_index_for_traits_callback_.Run(traits); | 231 return worker_pools_[GetEnvironmentIndexForTraits(traits)].get(); |
179 DCHECK_LT(index, worker_pools_.size()); | |
180 return worker_pools_[index].get(); | |
181 } | 232 } |
182 | 233 |
183 void TaskSchedulerImpl::ReEnqueueSequenceCallback( | 234 void TaskSchedulerImpl::ReEnqueueSequenceCallback( |
184 scoped_refptr<Sequence> sequence) { | 235 scoped_refptr<Sequence> sequence) { |
185 DCHECK(sequence); | 236 DCHECK(sequence); |
186 | 237 |
187 const SequenceSortKey sort_key = sequence->GetSortKey(); | 238 const SequenceSortKey sort_key = sequence->GetSortKey(); |
188 | 239 |
189 // The next task in |sequence| should run in a worker pool suited for its | 240 // The next task in |sequence| should run in a worker pool suited for its |
190 // traits, except for the priority which is adjusted to the highest priority | 241 // traits, except for the priority which is adjusted to the highest priority |
191 // in |sequence|. | 242 // in |sequence|. |
192 const TaskTraits traits = | 243 const TaskTraits traits = |
193 sequence->PeekTaskTraits().WithPriority(sort_key.priority()); | 244 sequence->PeekTaskTraits().WithPriority(sort_key.priority()); |
194 | 245 |
195 GetWorkerPoolForTraits(traits)->ReEnqueueSequence(std::move(sequence), | 246 GetWorkerPoolForTraits(traits)->ReEnqueueSequence(std::move(sequence), |
196 sort_key); | 247 sort_key); |
197 } | 248 } |
198 | 249 |
199 } // namespace internal | 250 } // namespace internal |
200 } // namespace base | 251 } // namespace base |
OLD | NEW |