| 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 |