| 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/scheduler_worker_pool_impl.h" | 5 #include "base/task_scheduler/scheduler_worker_pool_impl.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <unordered_set> | 10 #include <unordered_set> |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 void ShouldNotRunCallback() { | 164 void ShouldNotRunCallback() { |
| 165 ADD_FAILURE() << "Ran a task that shouldn't run."; | 165 ADD_FAILURE() << "Ran a task that shouldn't run."; |
| 166 } | 166 } |
| 167 | 167 |
| 168 } // namespace | 168 } // namespace |
| 169 | 169 |
| 170 TEST_P(TaskSchedulerWorkerPoolImplTest, PostTasks) { | 170 TEST_P(TaskSchedulerWorkerPoolImplTest, PostTasks) { |
| 171 // Create threads to post tasks. | 171 // Create threads to post tasks. |
| 172 std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks; | 172 std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks; |
| 173 for (size_t i = 0; i < kNumThreadsPostingTasks; ++i) { | 173 for (size_t i = 0; i < kNumThreadsPostingTasks; ++i) { |
| 174 threads_posting_tasks.push_back(WrapUnique(new ThreadPostingTasks( | 174 threads_posting_tasks.push_back(MakeUnique<ThreadPostingTasks>( |
| 175 worker_pool_.get(), GetParam(), WaitBeforePostTask::NO_WAIT, | 175 worker_pool_.get(), GetParam(), WaitBeforePostTask::NO_WAIT, |
| 176 PostNestedTask::NO))); | 176 PostNestedTask::NO)); |
| 177 threads_posting_tasks.back()->Start(); | 177 threads_posting_tasks.back()->Start(); |
| 178 } | 178 } |
| 179 | 179 |
| 180 // Wait for all tasks to run. | 180 // Wait for all tasks to run. |
| 181 for (const auto& thread_posting_tasks : threads_posting_tasks) { | 181 for (const auto& thread_posting_tasks : threads_posting_tasks) { |
| 182 thread_posting_tasks->Join(); | 182 thread_posting_tasks->Join(); |
| 183 thread_posting_tasks->factory()->WaitForAllTasksToRun(); | 183 thread_posting_tasks->factory()->WaitForAllTasksToRun(); |
| 184 } | 184 } |
| 185 | 185 |
| 186 // Wait until all workers are idle to be sure that no task accesses | 186 // Wait until all workers are idle to be sure that no task accesses |
| 187 // its TestTaskFactory after |thread_posting_tasks| is destroyed. | 187 // its TestTaskFactory after |thread_posting_tasks| is destroyed. |
| 188 worker_pool_->WaitForAllWorkersIdleForTesting(); | 188 worker_pool_->WaitForAllWorkersIdleForTesting(); |
| 189 } | 189 } |
| 190 | 190 |
| 191 TEST_P(TaskSchedulerWorkerPoolImplTest, PostTasksWaitAllWorkersIdle) { | 191 TEST_P(TaskSchedulerWorkerPoolImplTest, PostTasksWaitAllWorkersIdle) { |
| 192 // Create threads to post tasks. To verify that workers can sleep and be woken | 192 // Create threads to post tasks. To verify that workers can sleep and be woken |
| 193 // up when new tasks are posted, wait for all workers to become idle before | 193 // up when new tasks are posted, wait for all workers to become idle before |
| 194 // posting a new task. | 194 // posting a new task. |
| 195 std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks; | 195 std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks; |
| 196 for (size_t i = 0; i < kNumThreadsPostingTasks; ++i) { | 196 for (size_t i = 0; i < kNumThreadsPostingTasks; ++i) { |
| 197 threads_posting_tasks.push_back(WrapUnique(new ThreadPostingTasks( | 197 threads_posting_tasks.push_back(MakeUnique<ThreadPostingTasks>( |
| 198 worker_pool_.get(), GetParam(), | 198 worker_pool_.get(), GetParam(), |
| 199 WaitBeforePostTask::WAIT_FOR_ALL_WORKERS_IDLE, PostNestedTask::NO))); | 199 WaitBeforePostTask::WAIT_FOR_ALL_WORKERS_IDLE, PostNestedTask::NO)); |
| 200 threads_posting_tasks.back()->Start(); | 200 threads_posting_tasks.back()->Start(); |
| 201 } | 201 } |
| 202 | 202 |
| 203 // Wait for all tasks to run. | 203 // Wait for all tasks to run. |
| 204 for (const auto& thread_posting_tasks : threads_posting_tasks) { | 204 for (const auto& thread_posting_tasks : threads_posting_tasks) { |
| 205 thread_posting_tasks->Join(); | 205 thread_posting_tasks->Join(); |
| 206 thread_posting_tasks->factory()->WaitForAllTasksToRun(); | 206 thread_posting_tasks->factory()->WaitForAllTasksToRun(); |
| 207 } | 207 } |
| 208 | 208 |
| 209 // Wait until all workers are idle to be sure that no task accesses its | 209 // Wait until all workers are idle to be sure that no task accesses its |
| 210 // TestTaskFactory after |thread_posting_tasks| is destroyed. | 210 // TestTaskFactory after |thread_posting_tasks| is destroyed. |
| 211 worker_pool_->WaitForAllWorkersIdleForTesting(); | 211 worker_pool_->WaitForAllWorkersIdleForTesting(); |
| 212 } | 212 } |
| 213 | 213 |
| 214 TEST_P(TaskSchedulerWorkerPoolImplTest, NestedPostTasks) { | 214 TEST_P(TaskSchedulerWorkerPoolImplTest, NestedPostTasks) { |
| 215 // Create threads to post tasks. Each task posted by these threads will post | 215 // Create threads to post tasks. Each task posted by these threads will post |
| 216 // another task when it runs. | 216 // another task when it runs. |
| 217 std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks; | 217 std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks; |
| 218 for (size_t i = 0; i < kNumThreadsPostingTasks; ++i) { | 218 for (size_t i = 0; i < kNumThreadsPostingTasks; ++i) { |
| 219 threads_posting_tasks.push_back(WrapUnique(new ThreadPostingTasks( | 219 threads_posting_tasks.push_back(MakeUnique<ThreadPostingTasks>( |
| 220 worker_pool_.get(), GetParam(), WaitBeforePostTask::NO_WAIT, | 220 worker_pool_.get(), GetParam(), WaitBeforePostTask::NO_WAIT, |
| 221 PostNestedTask::YES))); | 221 PostNestedTask::YES)); |
| 222 threads_posting_tasks.back()->Start(); | 222 threads_posting_tasks.back()->Start(); |
| 223 } | 223 } |
| 224 | 224 |
| 225 // Wait for all tasks to run. | 225 // Wait for all tasks to run. |
| 226 for (const auto& thread_posting_tasks : threads_posting_tasks) { | 226 for (const auto& thread_posting_tasks : threads_posting_tasks) { |
| 227 thread_posting_tasks->Join(); | 227 thread_posting_tasks->Join(); |
| 228 thread_posting_tasks->factory()->WaitForAllTasksToRun(); | 228 thread_posting_tasks->factory()->WaitForAllTasksToRun(); |
| 229 } | 229 } |
| 230 | 230 |
| 231 // Wait until all workers are idle to be sure that no task accesses its | 231 // Wait until all workers are idle to be sure that no task accesses its |
| 232 // TestTaskFactory after |thread_posting_tasks| is destroyed. | 232 // TestTaskFactory after |thread_posting_tasks| is destroyed. |
| 233 worker_pool_->WaitForAllWorkersIdleForTesting(); | 233 worker_pool_->WaitForAllWorkersIdleForTesting(); |
| 234 } | 234 } |
| 235 | 235 |
| 236 TEST_P(TaskSchedulerWorkerPoolImplTest, PostTasksWithOneAvailableWorker) { | 236 TEST_P(TaskSchedulerWorkerPoolImplTest, PostTasksWithOneAvailableWorker) { |
| 237 // Post blocking tasks to keep all workers busy except one until |event| is | 237 // Post blocking tasks to keep all workers busy except one until |event| is |
| 238 // signaled. Use different factories so that tasks are added to different | 238 // signaled. Use different factories so that tasks are added to different |
| 239 // sequences and can run simultaneously when the execution mode is SEQUENCED. | 239 // sequences and can run simultaneously when the execution mode is SEQUENCED. |
| 240 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, | 240 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, |
| 241 WaitableEvent::InitialState::NOT_SIGNALED); | 241 WaitableEvent::InitialState::NOT_SIGNALED); |
| 242 std::vector<std::unique_ptr<test::TestTaskFactory>> blocked_task_factories; | 242 std::vector<std::unique_ptr<test::TestTaskFactory>> blocked_task_factories; |
| 243 for (size_t i = 0; i < (kNumWorkersInWorkerPool - 1); ++i) { | 243 for (size_t i = 0; i < (kNumWorkersInWorkerPool - 1); ++i) { |
| 244 blocked_task_factories.push_back(WrapUnique(new test::TestTaskFactory( | 244 blocked_task_factories.push_back(MakeUnique<test::TestTaskFactory>( |
| 245 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()), | 245 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()), |
| 246 GetParam()))); | 246 GetParam())); |
| 247 EXPECT_TRUE(blocked_task_factories.back()->PostTask( | 247 EXPECT_TRUE(blocked_task_factories.back()->PostTask( |
| 248 PostNestedTask::NO, Bind(&WaitableEvent::Wait, Unretained(&event)))); | 248 PostNestedTask::NO, Bind(&WaitableEvent::Wait, Unretained(&event)))); |
| 249 blocked_task_factories.back()->WaitForAllTasksToRun(); | 249 blocked_task_factories.back()->WaitForAllTasksToRun(); |
| 250 } | 250 } |
| 251 | 251 |
| 252 // Post |kNumTasksPostedPerThread| tasks that should all run despite the fact | 252 // Post |kNumTasksPostedPerThread| tasks that should all run despite the fact |
| 253 // that only one worker in |worker_pool_| isn't busy. | 253 // that only one worker in |worker_pool_| isn't busy. |
| 254 test::TestTaskFactory short_task_factory( | 254 test::TestTaskFactory short_task_factory( |
| 255 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()), | 255 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()), |
| 256 GetParam()); | 256 GetParam()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 268 | 268 |
| 269 TEST_P(TaskSchedulerWorkerPoolImplTest, Saturate) { | 269 TEST_P(TaskSchedulerWorkerPoolImplTest, Saturate) { |
| 270 // Verify that it is possible to have |kNumWorkersInWorkerPool| | 270 // Verify that it is possible to have |kNumWorkersInWorkerPool| |
| 271 // tasks/sequences running simultaneously. Use different factories so that the | 271 // tasks/sequences running simultaneously. Use different factories so that the |
| 272 // blocking tasks are added to different sequences and can run simultaneously | 272 // blocking tasks are added to different sequences and can run simultaneously |
| 273 // when the execution mode is SEQUENCED. | 273 // when the execution mode is SEQUENCED. |
| 274 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, | 274 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, |
| 275 WaitableEvent::InitialState::NOT_SIGNALED); | 275 WaitableEvent::InitialState::NOT_SIGNALED); |
| 276 std::vector<std::unique_ptr<test::TestTaskFactory>> factories; | 276 std::vector<std::unique_ptr<test::TestTaskFactory>> factories; |
| 277 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { | 277 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { |
| 278 factories.push_back(WrapUnique(new test::TestTaskFactory( | 278 factories.push_back(MakeUnique<test::TestTaskFactory>( |
| 279 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()), | 279 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()), |
| 280 GetParam()))); | 280 GetParam())); |
| 281 EXPECT_TRUE(factories.back()->PostTask( | 281 EXPECT_TRUE(factories.back()->PostTask( |
| 282 PostNestedTask::NO, Bind(&WaitableEvent::Wait, Unretained(&event)))); | 282 PostNestedTask::NO, Bind(&WaitableEvent::Wait, Unretained(&event)))); |
| 283 factories.back()->WaitForAllTasksToRun(); | 283 factories.back()->WaitForAllTasksToRun(); |
| 284 } | 284 } |
| 285 | 285 |
| 286 // Release tasks waiting on |event|. | 286 // Release tasks waiting on |event|. |
| 287 event.Signal(); | 287 event.Signal(); |
| 288 | 288 |
| 289 // Wait until all workers are idle to be sure that no task accesses | 289 // Wait until all workers are idle to be sure that no task accesses |
| 290 // its TestTaskFactory after it is destroyed. | 290 // its TestTaskFactory after it is destroyed. |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 548 count_waiter->Wait(); | 548 count_waiter->Wait(); |
| 549 | 549 |
| 550 EXPECT_GT(subtle::NoBarrier_Load(&zero_tls_values_), 0); | 550 EXPECT_GT(subtle::NoBarrier_Load(&zero_tls_values_), 0); |
| 551 | 551 |
| 552 // Release tasks waiting on |waiter_|. | 552 // Release tasks waiting on |waiter_|. |
| 553 waiter_.Signal(); | 553 waiter_.Signal(); |
| 554 } | 554 } |
| 555 | 555 |
| 556 } // namespace internal | 556 } // namespace internal |
| 557 } // namespace base | 557 } // namespace base |
| OLD | NEW |