| 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 12 matching lines...) Expand all Loading... |
| 23 #include "base/synchronization/condition_variable.h" | 23 #include "base/synchronization/condition_variable.h" |
| 24 #include "base/synchronization/lock.h" | 24 #include "base/synchronization/lock.h" |
| 25 #include "base/synchronization/waitable_event.h" | 25 #include "base/synchronization/waitable_event.h" |
| 26 #include "base/task_runner.h" | 26 #include "base/task_runner.h" |
| 27 #include "base/task_scheduler/delayed_task_manager.h" | 27 #include "base/task_scheduler/delayed_task_manager.h" |
| 28 #include "base/task_scheduler/scheduler_worker_pool_params.h" | 28 #include "base/task_scheduler/scheduler_worker_pool_params.h" |
| 29 #include "base/task_scheduler/sequence.h" | 29 #include "base/task_scheduler/sequence.h" |
| 30 #include "base/task_scheduler/sequence_sort_key.h" | 30 #include "base/task_scheduler/sequence_sort_key.h" |
| 31 #include "base/task_scheduler/task_tracker.h" | 31 #include "base/task_scheduler/task_tracker.h" |
| 32 #include "base/task_scheduler/test_task_factory.h" | 32 #include "base/task_scheduler/test_task_factory.h" |
| 33 #include "base/task_scheduler/test_utils.h" |
| 33 #include "base/test/gtest_util.h" | 34 #include "base/test/gtest_util.h" |
| 34 #include "base/test/test_simple_task_runner.h" | 35 #include "base/test/test_simple_task_runner.h" |
| 35 #include "base/test/test_timeouts.h" | 36 #include "base/test/test_timeouts.h" |
| 36 #include "base/threading/platform_thread.h" | 37 #include "base/threading/platform_thread.h" |
| 37 #include "base/threading/simple_thread.h" | 38 #include "base/threading/simple_thread.h" |
| 38 #include "base/threading/thread.h" | 39 #include "base/threading/thread.h" |
| 39 #include "base/threading/thread_checker_impl.h" | 40 #include "base/threading/thread_checker_impl.h" |
| 40 #include "base/threading/thread_local_storage.h" | 41 #include "base/threading/thread_local_storage.h" |
| 41 #include "base/threading/thread_restrictions.h" | 42 #include "base/threading/thread_restrictions.h" |
| 42 #include "base/time/time.h" | 43 #include "base/time/time.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 53 // small timeout is used. This results in many spurious wake ups before a worker | 54 // small timeout is used. This results in many spurious wake ups before a worker |
| 54 // is allowed to detach. | 55 // is allowed to detach. |
| 55 constexpr TimeDelta kReclaimTimeForDetachTests = | 56 constexpr TimeDelta kReclaimTimeForDetachTests = |
| 56 TimeDelta::FromMilliseconds(500); | 57 TimeDelta::FromMilliseconds(500); |
| 57 constexpr TimeDelta kExtraTimeToWaitForDetach = | 58 constexpr TimeDelta kExtraTimeToWaitForDetach = |
| 58 TimeDelta::FromSeconds(1); | 59 TimeDelta::FromSeconds(1); |
| 59 | 60 |
| 60 using IORestriction = SchedulerWorkerPoolParams::IORestriction; | 61 using IORestriction = SchedulerWorkerPoolParams::IORestriction; |
| 61 | 62 |
| 62 class TaskSchedulerWorkerPoolImplTest | 63 class TaskSchedulerWorkerPoolImplTest |
| 63 : public testing::TestWithParam<ExecutionMode> { | 64 : public testing::TestWithParam<test::ExecutionMode> { |
| 64 protected: | 65 protected: |
| 65 TaskSchedulerWorkerPoolImplTest() | 66 TaskSchedulerWorkerPoolImplTest() |
| 66 : service_thread_("TaskSchedulerServiceThread") {} | 67 : service_thread_("TaskSchedulerServiceThread") {} |
| 67 | 68 |
| 68 void SetUp() override { | 69 void SetUp() override { |
| 69 InitializeWorkerPool(TimeDelta::Max(), kNumWorkersInWorkerPool); | 70 InitializeWorkerPool(TimeDelta::Max(), kNumWorkersInWorkerPool); |
| 70 } | 71 } |
| 71 | 72 |
| 72 void TearDown() override { | 73 void TearDown() override { |
| 73 service_thread_.Stop(); | 74 service_thread_.Stop(); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 103 // In production code, this callback would be implemented by the | 104 // In production code, this callback would be implemented by the |
| 104 // TaskScheduler which would first determine which PriorityQueue the | 105 // TaskScheduler which would first determine which PriorityQueue the |
| 105 // sequence must be re-enqueued. | 106 // sequence must be re-enqueued. |
| 106 const SequenceSortKey sort_key(sequence->GetSortKey()); | 107 const SequenceSortKey sort_key(sequence->GetSortKey()); |
| 107 worker_pool_->ReEnqueueSequence(std::move(sequence), sort_key); | 108 worker_pool_->ReEnqueueSequence(std::move(sequence), sort_key); |
| 108 } | 109 } |
| 109 | 110 |
| 110 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolImplTest); | 111 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolImplTest); |
| 111 }; | 112 }; |
| 112 | 113 |
| 114 scoped_refptr<TaskRunner> CreateTaskRunnerWithExecutionMode( |
| 115 SchedulerWorkerPoolImpl* worker_pool, |
| 116 test::ExecutionMode execution_mode) { |
| 117 switch (execution_mode) { |
| 118 case test::ExecutionMode::PARALLEL: |
| 119 return worker_pool->CreateTaskRunnerWithTraits(TaskTraits()); |
| 120 case test::ExecutionMode::SEQUENCED: |
| 121 return worker_pool->CreateSequencedTaskRunnerWithTraits(TaskTraits()); |
| 122 case test::ExecutionMode::SINGLE_THREADED: |
| 123 return worker_pool->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()); |
| 124 } |
| 125 ADD_FAILURE() << "Unknown ExecutionMode"; |
| 126 return nullptr; |
| 127 } |
| 128 |
| 113 using PostNestedTask = test::TestTaskFactory::PostNestedTask; | 129 using PostNestedTask = test::TestTaskFactory::PostNestedTask; |
| 114 | 130 |
| 115 class ThreadPostingTasks : public SimpleThread { | 131 class ThreadPostingTasks : public SimpleThread { |
| 116 public: | 132 public: |
| 117 enum class WaitBeforePostTask { | 133 enum class WaitBeforePostTask { |
| 118 NO_WAIT, | 134 NO_WAIT, |
| 119 WAIT_FOR_ALL_WORKERS_IDLE, | 135 WAIT_FOR_ALL_WORKERS_IDLE, |
| 120 }; | 136 }; |
| 121 | 137 |
| 122 // Constructs a thread that posts tasks to |worker_pool| through an | 138 // Constructs a thread that posts tasks to |worker_pool| through an |
| 123 // |execution_mode| task runner. If |wait_before_post_task| is | 139 // |execution_mode| task runner. If |wait_before_post_task| is |
| 124 // WAIT_FOR_ALL_WORKERS_IDLE, the thread waits until all workers in | 140 // WAIT_FOR_ALL_WORKERS_IDLE, the thread waits until all workers in |
| 125 // |worker_pool| are idle before posting a new task. If |post_nested_task| is | 141 // |worker_pool| are idle before posting a new task. If |post_nested_task| is |
| 126 // YES, each task posted by this thread posts another task when it runs. | 142 // YES, each task posted by this thread posts another task when it runs. |
| 127 ThreadPostingTasks(SchedulerWorkerPoolImpl* worker_pool, | 143 ThreadPostingTasks(SchedulerWorkerPoolImpl* worker_pool, |
| 128 ExecutionMode execution_mode, | 144 test::ExecutionMode execution_mode, |
| 129 WaitBeforePostTask wait_before_post_task, | 145 WaitBeforePostTask wait_before_post_task, |
| 130 PostNestedTask post_nested_task) | 146 PostNestedTask post_nested_task) |
| 131 : SimpleThread("ThreadPostingTasks"), | 147 : SimpleThread("ThreadPostingTasks"), |
| 132 worker_pool_(worker_pool), | 148 worker_pool_(worker_pool), |
| 133 wait_before_post_task_(wait_before_post_task), | 149 wait_before_post_task_(wait_before_post_task), |
| 134 post_nested_task_(post_nested_task), | 150 post_nested_task_(post_nested_task), |
| 135 factory_(worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), | 151 factory_(CreateTaskRunnerWithExecutionMode(worker_pool, execution_mode), |
| 136 execution_mode), | |
| 137 execution_mode) { | 152 execution_mode) { |
| 138 DCHECK(worker_pool_); | 153 DCHECK(worker_pool_); |
| 139 } | 154 } |
| 140 | 155 |
| 141 const test::TestTaskFactory* factory() const { return &factory_; } | 156 const test::TestTaskFactory* factory() const { return &factory_; } |
| 142 | 157 |
| 143 private: | 158 private: |
| 144 void Run() override { | 159 void Run() override { |
| 145 EXPECT_FALSE(factory_.task_runner()->RunsTasksOnCurrentThread()); | 160 EXPECT_FALSE(factory_.task_runner()->RunsTasksOnCurrentThread()); |
| 146 | 161 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 | 253 |
| 239 TEST_P(TaskSchedulerWorkerPoolImplTest, PostTasksWithOneAvailableWorker) { | 254 TEST_P(TaskSchedulerWorkerPoolImplTest, PostTasksWithOneAvailableWorker) { |
| 240 // Post blocking tasks to keep all workers busy except one until |event| is | 255 // Post blocking tasks to keep all workers busy except one until |event| is |
| 241 // signaled. Use different factories so that tasks are added to different | 256 // signaled. Use different factories so that tasks are added to different |
| 242 // sequences and can run simultaneously when the execution mode is SEQUENCED. | 257 // sequences and can run simultaneously when the execution mode is SEQUENCED. |
| 243 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, | 258 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, |
| 244 WaitableEvent::InitialState::NOT_SIGNALED); | 259 WaitableEvent::InitialState::NOT_SIGNALED); |
| 245 std::vector<std::unique_ptr<test::TestTaskFactory>> blocked_task_factories; | 260 std::vector<std::unique_ptr<test::TestTaskFactory>> blocked_task_factories; |
| 246 for (size_t i = 0; i < (kNumWorkersInWorkerPool - 1); ++i) { | 261 for (size_t i = 0; i < (kNumWorkersInWorkerPool - 1); ++i) { |
| 247 blocked_task_factories.push_back(MakeUnique<test::TestTaskFactory>( | 262 blocked_task_factories.push_back(MakeUnique<test::TestTaskFactory>( |
| 248 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()), | 263 CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()), |
| 249 GetParam())); | 264 GetParam())); |
| 250 EXPECT_TRUE(blocked_task_factories.back()->PostTask( | 265 EXPECT_TRUE(blocked_task_factories.back()->PostTask( |
| 251 PostNestedTask::NO, Bind(&WaitableEvent::Wait, Unretained(&event)))); | 266 PostNestedTask::NO, Bind(&WaitableEvent::Wait, Unretained(&event)))); |
| 252 blocked_task_factories.back()->WaitForAllTasksToRun(); | 267 blocked_task_factories.back()->WaitForAllTasksToRun(); |
| 253 } | 268 } |
| 254 | 269 |
| 255 // Post |kNumTasksPostedPerThread| tasks that should all run despite the fact | 270 // Post |kNumTasksPostedPerThread| tasks that should all run despite the fact |
| 256 // that only one worker in |worker_pool_| isn't busy. | 271 // that only one worker in |worker_pool_| isn't busy. |
| 257 test::TestTaskFactory short_task_factory( | 272 test::TestTaskFactory short_task_factory( |
| 258 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()), | 273 CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()), |
| 259 GetParam()); | 274 GetParam()); |
| 260 for (size_t i = 0; i < kNumTasksPostedPerThread; ++i) | 275 for (size_t i = 0; i < kNumTasksPostedPerThread; ++i) |
| 261 EXPECT_TRUE(short_task_factory.PostTask(PostNestedTask::NO, Closure())); | 276 EXPECT_TRUE(short_task_factory.PostTask(PostNestedTask::NO, Closure())); |
| 262 short_task_factory.WaitForAllTasksToRun(); | 277 short_task_factory.WaitForAllTasksToRun(); |
| 263 | 278 |
| 264 // Release tasks waiting on |event|. | 279 // Release tasks waiting on |event|. |
| 265 event.Signal(); | 280 event.Signal(); |
| 266 | 281 |
| 267 // Wait until all workers are idle to be sure that no task accesses | 282 // Wait until all workers are idle to be sure that no task accesses |
| 268 // its TestTaskFactory after it is destroyed. | 283 // its TestTaskFactory after it is destroyed. |
| 269 worker_pool_->WaitForAllWorkersIdleForTesting(); | 284 worker_pool_->WaitForAllWorkersIdleForTesting(); |
| 270 } | 285 } |
| 271 | 286 |
| 272 TEST_P(TaskSchedulerWorkerPoolImplTest, Saturate) { | 287 TEST_P(TaskSchedulerWorkerPoolImplTest, Saturate) { |
| 273 // Verify that it is possible to have |kNumWorkersInWorkerPool| | 288 // Verify that it is possible to have |kNumWorkersInWorkerPool| |
| 274 // tasks/sequences running simultaneously. Use different factories so that the | 289 // tasks/sequences running simultaneously. Use different factories so that the |
| 275 // blocking tasks are added to different sequences and can run simultaneously | 290 // blocking tasks are added to different sequences and can run simultaneously |
| 276 // when the execution mode is SEQUENCED. | 291 // when the execution mode is SEQUENCED. |
| 277 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, | 292 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, |
| 278 WaitableEvent::InitialState::NOT_SIGNALED); | 293 WaitableEvent::InitialState::NOT_SIGNALED); |
| 279 std::vector<std::unique_ptr<test::TestTaskFactory>> factories; | 294 std::vector<std::unique_ptr<test::TestTaskFactory>> factories; |
| 280 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { | 295 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { |
| 281 factories.push_back(MakeUnique<test::TestTaskFactory>( | 296 factories.push_back(MakeUnique<test::TestTaskFactory>( |
| 282 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()), | 297 CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()), |
| 283 GetParam())); | 298 GetParam())); |
| 284 EXPECT_TRUE(factories.back()->PostTask( | 299 EXPECT_TRUE(factories.back()->PostTask( |
| 285 PostNestedTask::NO, Bind(&WaitableEvent::Wait, Unretained(&event)))); | 300 PostNestedTask::NO, Bind(&WaitableEvent::Wait, Unretained(&event)))); |
| 286 factories.back()->WaitForAllTasksToRun(); | 301 factories.back()->WaitForAllTasksToRun(); |
| 287 } | 302 } |
| 288 | 303 |
| 289 // Release tasks waiting on |event|. | 304 // Release tasks waiting on |event|. |
| 290 event.Signal(); | 305 event.Signal(); |
| 291 | 306 |
| 292 // Wait until all workers are idle to be sure that no task accesses | 307 // Wait until all workers are idle to be sure that no task accesses |
| 293 // its TestTaskFactory after it is destroyed. | 308 // its TestTaskFactory after it is destroyed. |
| 294 worker_pool_->WaitForAllWorkersIdleForTesting(); | 309 worker_pool_->WaitForAllWorkersIdleForTesting(); |
| 295 } | 310 } |
| 296 | 311 |
| 297 // Verify that a Task can't be posted after shutdown. | 312 // Verify that a Task can't be posted after shutdown. |
| 298 TEST_P(TaskSchedulerWorkerPoolImplTest, PostTaskAfterShutdown) { | 313 TEST_P(TaskSchedulerWorkerPoolImplTest, PostTaskAfterShutdown) { |
| 299 auto task_runner = | 314 auto task_runner = |
| 300 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()); | 315 CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()); |
| 301 task_tracker_.Shutdown(); | 316 task_tracker_.Shutdown(); |
| 302 EXPECT_FALSE(task_runner->PostTask(FROM_HERE, Bind(&ShouldNotRunCallback))); | 317 EXPECT_FALSE(task_runner->PostTask(FROM_HERE, Bind(&ShouldNotRunCallback))); |
| 303 } | 318 } |
| 304 | 319 |
| 305 // Verify that a Task runs shortly after its delay expires. | 320 // Verify that a Task runs shortly after its delay expires. |
| 306 TEST_P(TaskSchedulerWorkerPoolImplTest, PostDelayedTask) { | 321 TEST_P(TaskSchedulerWorkerPoolImplTest, PostDelayedTask) { |
| 307 TimeTicks start_time = TimeTicks::Now(); | 322 TimeTicks start_time = TimeTicks::Now(); |
| 308 | 323 |
| 309 // Post a task with a short delay. | 324 // Post a task with a short delay. |
| 310 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, | 325 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, |
| 311 WaitableEvent::InitialState::NOT_SIGNALED); | 326 WaitableEvent::InitialState::NOT_SIGNALED); |
| 312 EXPECT_TRUE(worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()) | 327 EXPECT_TRUE(CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()) |
| 313 ->PostDelayedTask(FROM_HERE, Bind(&WaitableEvent::Signal, | 328 ->PostDelayedTask(FROM_HERE, Bind(&WaitableEvent::Signal, |
| 314 Unretained(&task_ran)), | 329 Unretained(&task_ran)), |
| 315 TestTimeouts::tiny_timeout())); | 330 TestTimeouts::tiny_timeout())); |
| 316 | 331 |
| 317 // Wait until the task runs. | 332 // Wait until the task runs. |
| 318 task_ran.Wait(); | 333 task_ran.Wait(); |
| 319 | 334 |
| 320 // Expect the task to run after its delay expires, but not more than 250 ms | 335 // Expect the task to run after its delay expires, but not more than 250 ms |
| 321 // after that. | 336 // after that. |
| 322 const TimeDelta actual_delay = TimeTicks::Now() - start_time; | 337 const TimeDelta actual_delay = TimeTicks::Now() - start_time; |
| 323 EXPECT_GE(actual_delay, TestTimeouts::tiny_timeout()); | 338 EXPECT_GE(actual_delay, TestTimeouts::tiny_timeout()); |
| 324 EXPECT_LT(actual_delay, | 339 EXPECT_LT(actual_delay, |
| 325 TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout()); | 340 TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout()); |
| 326 } | 341 } |
| 327 | 342 |
| 328 // Verify that the RunsTasksOnCurrentThread() method of a SEQUENCED TaskRunner | 343 // Verify that the RunsTasksOnCurrentThread() method of a SEQUENCED TaskRunner |
| 329 // returns false when called from a task that isn't part of the sequence. | 344 // returns false when called from a task that isn't part of the sequence. |
| 330 TEST_P(TaskSchedulerWorkerPoolImplTest, SequencedRunsTasksOnCurrentThread) { | 345 TEST_P(TaskSchedulerWorkerPoolImplTest, SequencedRunsTasksOnCurrentThread) { |
| 331 scoped_refptr<TaskRunner> task_runner( | 346 scoped_refptr<TaskRunner> task_runner( |
| 332 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam())); | 347 CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam())); |
| 333 scoped_refptr<TaskRunner> sequenced_task_runner( | 348 scoped_refptr<SequencedTaskRunner> sequenced_task_runner( |
| 334 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), | 349 worker_pool_->CreateSequencedTaskRunnerWithTraits(TaskTraits())); |
| 335 ExecutionMode::SEQUENCED)); | |
| 336 | 350 |
| 337 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, | 351 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, |
| 338 WaitableEvent::InitialState::NOT_SIGNALED); | 352 WaitableEvent::InitialState::NOT_SIGNALED); |
| 339 task_runner->PostTask( | 353 task_runner->PostTask( |
| 340 FROM_HERE, | 354 FROM_HERE, |
| 341 Bind( | 355 Bind( |
| 342 [](scoped_refptr<TaskRunner> sequenced_task_runner, | 356 [](scoped_refptr<TaskRunner> sequenced_task_runner, |
| 343 WaitableEvent* task_ran) { | 357 WaitableEvent* task_ran) { |
| 344 EXPECT_FALSE(sequenced_task_runner->RunsTasksOnCurrentThread()); | 358 EXPECT_FALSE(sequenced_task_runner->RunsTasksOnCurrentThread()); |
| 345 // Tests that use TestTaskFactory already verify that | 359 // Tests that use TestTaskFactory already verify that |
| 346 // RunsTasksOnCurrentThread() returns true when appropriate. | 360 // RunsTasksOnCurrentThread() returns true when appropriate. |
| 347 task_ran->Signal(); | 361 task_ran->Signal(); |
| 348 }, | 362 }, |
| 349 sequenced_task_runner, Unretained(&task_ran))); | 363 sequenced_task_runner, Unretained(&task_ran))); |
| 350 task_ran.Wait(); | 364 task_ran.Wait(); |
| 351 } | 365 } |
| 352 | 366 |
| 353 INSTANTIATE_TEST_CASE_P(Parallel, | 367 INSTANTIATE_TEST_CASE_P(Parallel, |
| 354 TaskSchedulerWorkerPoolImplTest, | 368 TaskSchedulerWorkerPoolImplTest, |
| 355 ::testing::Values(ExecutionMode::PARALLEL)); | 369 ::testing::Values(test::ExecutionMode::PARALLEL)); |
| 356 INSTANTIATE_TEST_CASE_P(Sequenced, | 370 INSTANTIATE_TEST_CASE_P(Sequenced, |
| 357 TaskSchedulerWorkerPoolImplTest, | 371 TaskSchedulerWorkerPoolImplTest, |
| 358 ::testing::Values(ExecutionMode::SEQUENCED)); | 372 ::testing::Values(test::ExecutionMode::SEQUENCED)); |
| 359 INSTANTIATE_TEST_CASE_P(SingleThreaded, | 373 INSTANTIATE_TEST_CASE_P( |
| 360 TaskSchedulerWorkerPoolImplTest, | 374 SingleThreaded, |
| 361 ::testing::Values(ExecutionMode::SINGLE_THREADED)); | 375 TaskSchedulerWorkerPoolImplTest, |
| 376 ::testing::Values(test::ExecutionMode::SINGLE_THREADED)); |
| 362 | 377 |
| 363 namespace { | 378 namespace { |
| 364 | 379 |
| 365 void NotReachedReEnqueueSequenceCallback(scoped_refptr<Sequence> sequence) { | 380 void NotReachedReEnqueueSequenceCallback(scoped_refptr<Sequence> sequence) { |
| 366 ADD_FAILURE() | 381 ADD_FAILURE() |
| 367 << "Unexpected invocation of NotReachedReEnqueueSequenceCallback."; | 382 << "Unexpected invocation of NotReachedReEnqueueSequenceCallback."; |
| 368 } | 383 } |
| 369 | 384 |
| 370 // Verifies that the current thread allows I/O if |io_restriction| is ALLOWED | 385 // Verifies that the current thread allows I/O if |io_restriction| is ALLOWED |
| 371 // and disallows it otherwise. Signals |event| before returning. | 386 // and disallows it otherwise. Signals |event| before returning. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 400 auto worker_pool = SchedulerWorkerPoolImpl::Create( | 415 auto worker_pool = SchedulerWorkerPoolImpl::Create( |
| 401 SchedulerWorkerPoolParams("TestWorkerPoolWithParam", | 416 SchedulerWorkerPoolParams("TestWorkerPoolWithParam", |
| 402 ThreadPriority::NORMAL, GetParam(), 1U, | 417 ThreadPriority::NORMAL, GetParam(), 1U, |
| 403 TimeDelta::Max()), | 418 TimeDelta::Max()), |
| 404 Bind(&NotReachedReEnqueueSequenceCallback), &task_tracker, | 419 Bind(&NotReachedReEnqueueSequenceCallback), &task_tracker, |
| 405 &delayed_task_manager); | 420 &delayed_task_manager); |
| 406 ASSERT_TRUE(worker_pool); | 421 ASSERT_TRUE(worker_pool); |
| 407 | 422 |
| 408 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, | 423 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, |
| 409 WaitableEvent::InitialState::NOT_SIGNALED); | 424 WaitableEvent::InitialState::NOT_SIGNALED); |
| 410 worker_pool->CreateTaskRunnerWithTraits(TaskTraits(), ExecutionMode::PARALLEL) | 425 worker_pool->CreateTaskRunnerWithTraits(TaskTraits()) |
| 411 ->PostTask(FROM_HERE, Bind(&ExpectIORestriction, GetParam(), &task_ran)); | 426 ->PostTask(FROM_HERE, Bind(&ExpectIORestriction, GetParam(), &task_ran)); |
| 412 task_ran.Wait(); | 427 task_ran.Wait(); |
| 413 | 428 |
| 414 worker_pool->JoinForTesting(); | 429 worker_pool->JoinForTesting(); |
| 415 } | 430 } |
| 416 | 431 |
| 417 INSTANTIATE_TEST_CASE_P(IOAllowed, | 432 INSTANTIATE_TEST_CASE_P(IOAllowed, |
| 418 TaskSchedulerWorkerPoolImplIORestrictionTest, | 433 TaskSchedulerWorkerPoolImplIORestrictionTest, |
| 419 ::testing::Values(IORestriction::ALLOWED)); | 434 ::testing::Values(IORestriction::ALLOWED)); |
| 420 INSTANTIATE_TEST_CASE_P(IODisallowed, | 435 INSTANTIATE_TEST_CASE_P(IODisallowed, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 445 std::unique_ptr<ThreadCheckerImpl> thread_checker_; | 460 std::unique_ptr<ThreadCheckerImpl> thread_checker_; |
| 446 | 461 |
| 447 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolSingleThreadedTest); | 462 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolSingleThreadedTest); |
| 448 }; | 463 }; |
| 449 | 464 |
| 450 } // namespace | 465 } // namespace |
| 451 | 466 |
| 452 // Verify that thread resources for a single thread remain. | 467 // Verify that thread resources for a single thread remain. |
| 453 TEST_F(TaskSchedulerWorkerPoolSingleThreadedTest, SingleThreadTask) { | 468 TEST_F(TaskSchedulerWorkerPoolSingleThreadedTest, SingleThreadTask) { |
| 454 auto single_thread_task_runner = | 469 auto single_thread_task_runner = |
| 455 worker_pool_->CreateTaskRunnerWithTraits( | 470 worker_pool_->CreateSingleThreadTaskRunnerWithTraits( |
| 456 TaskTraits(). | 471 TaskTraits().WithShutdownBehavior( |
| 457 WithShutdownBehavior(TaskShutdownBehavior::BLOCK_SHUTDOWN), | 472 TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| 458 ExecutionMode::SINGLE_THREADED); | |
| 459 single_thread_task_runner->PostTask( | 473 single_thread_task_runner->PostTask( |
| 460 FROM_HERE, | 474 FROM_HERE, |
| 461 Bind(&TaskSchedulerWorkerPoolSingleThreadedTest::InitializeThreadChecker, | 475 Bind(&TaskSchedulerWorkerPoolSingleThreadedTest::InitializeThreadChecker, |
| 462 Unretained(this))); | 476 Unretained(this))); |
| 463 WaitableEvent task_waiter(WaitableEvent::ResetPolicy::AUTOMATIC, | 477 WaitableEvent task_waiter(WaitableEvent::ResetPolicy::AUTOMATIC, |
| 464 WaitableEvent::InitialState::NOT_SIGNALED); | 478 WaitableEvent::InitialState::NOT_SIGNALED); |
| 465 single_thread_task_runner->PostTask( | 479 single_thread_task_runner->PostTask( |
| 466 FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&task_waiter))); | 480 FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&task_waiter))); |
| 467 task_waiter.Wait(); | 481 task_waiter.Wait(); |
| 468 worker_pool_->WaitForAllWorkersIdleForTesting(); | 482 worker_pool_->WaitForAllWorkersIdleForTesting(); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolCheckTlsReuse); | 534 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolCheckTlsReuse); |
| 521 }; | 535 }; |
| 522 | 536 |
| 523 } // namespace | 537 } // namespace |
| 524 | 538 |
| 525 // Checks that at least one thread has detached by checking the TLS. | 539 // Checks that at least one thread has detached by checking the TLS. |
| 526 TEST_F(TaskSchedulerWorkerPoolCheckTlsReuse, CheckDetachedThreads) { | 540 TEST_F(TaskSchedulerWorkerPoolCheckTlsReuse, CheckDetachedThreads) { |
| 527 // Saturate the threads and mark each thread with a magic TLS value. | 541 // Saturate the threads and mark each thread with a magic TLS value. |
| 528 std::vector<std::unique_ptr<test::TestTaskFactory>> factories; | 542 std::vector<std::unique_ptr<test::TestTaskFactory>> factories; |
| 529 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { | 543 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { |
| 530 factories.push_back(WrapUnique(new test::TestTaskFactory( | 544 factories.push_back(MakeUnique<test::TestTaskFactory>( |
| 531 worker_pool_->CreateTaskRunnerWithTraits( | 545 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits()), |
| 532 TaskTraits(), ExecutionMode::PARALLEL), | 546 test::ExecutionMode::PARALLEL)); |
| 533 ExecutionMode::PARALLEL))); | |
| 534 ASSERT_TRUE(factories.back()->PostTask( | 547 ASSERT_TRUE(factories.back()->PostTask( |
| 535 PostNestedTask::NO, | 548 PostNestedTask::NO, |
| 536 Bind(&TaskSchedulerWorkerPoolCheckTlsReuse::SetTlsValueAndWait, | 549 Bind(&TaskSchedulerWorkerPoolCheckTlsReuse::SetTlsValueAndWait, |
| 537 Unretained(this)))); | 550 Unretained(this)))); |
| 538 factories.back()->WaitForAllTasksToRun(); | 551 factories.back()->WaitForAllTasksToRun(); |
| 539 } | 552 } |
| 540 | 553 |
| 541 // Release tasks waiting on |waiter_|. | 554 // Release tasks waiting on |waiter_|. |
| 542 waiter_.Signal(); | 555 waiter_.Signal(); |
| 543 worker_pool_->WaitForAllWorkersIdleForTesting(); | 556 worker_pool_->WaitForAllWorkersIdleForTesting(); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 | 606 |
| 594 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolHistogramTest); | 607 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolHistogramTest); |
| 595 }; | 608 }; |
| 596 | 609 |
| 597 } // namespace | 610 } // namespace |
| 598 | 611 |
| 599 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaits) { | 612 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaits) { |
| 600 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, | 613 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, |
| 601 WaitableEvent::InitialState::NOT_SIGNALED); | 614 WaitableEvent::InitialState::NOT_SIGNALED); |
| 602 InitializeWorkerPool(TimeDelta::Max(), kNumWorkersInWorkerPool); | 615 InitializeWorkerPool(TimeDelta::Max(), kNumWorkersInWorkerPool); |
| 603 auto task_runner = worker_pool_->CreateTaskRunnerWithTraits( | 616 auto task_runner = |
| 604 TaskTraits(), ExecutionMode::SEQUENCED); | 617 worker_pool_->CreateSequencedTaskRunnerWithTraits(TaskTraits()); |
| 605 | 618 |
| 606 // Post a task. | 619 // Post a task. |
| 607 task_runner->PostTask(FROM_HERE, | 620 task_runner->PostTask(FROM_HERE, |
| 608 Bind(&WaitableEvent::Wait, Unretained(&event))); | 621 Bind(&WaitableEvent::Wait, Unretained(&event))); |
| 609 | 622 |
| 610 // Post 2 more tasks while the first task hasn't completed its execution. It | 623 // Post 2 more tasks while the first task hasn't completed its execution. It |
| 611 // is guaranteed that these tasks will run immediately after the first task, | 624 // is guaranteed that these tasks will run immediately after the first task, |
| 612 // without allowing the worker to sleep. | 625 // without allowing the worker to sleep. |
| 613 task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); | 626 task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); |
| 614 task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); | 627 task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 637 signal_event->Signal(); | 650 signal_event->Signal(); |
| 638 wait_event->Wait(); | 651 wait_event->Wait(); |
| 639 } | 652 } |
| 640 | 653 |
| 641 } // namespace | 654 } // namespace |
| 642 | 655 |
| 643 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaitsWithDetach) { | 656 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaitsWithDetach) { |
| 644 WaitableEvent tasks_can_exit_event(WaitableEvent::ResetPolicy::MANUAL, | 657 WaitableEvent tasks_can_exit_event(WaitableEvent::ResetPolicy::MANUAL, |
| 645 WaitableEvent::InitialState::NOT_SIGNALED); | 658 WaitableEvent::InitialState::NOT_SIGNALED); |
| 646 InitializeWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); | 659 InitializeWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); |
| 647 auto task_runner = worker_pool_->CreateTaskRunnerWithTraits( | 660 auto task_runner = worker_pool_->CreateTaskRunnerWithTraits(TaskTraits()); |
| 648 TaskTraits(), ExecutionMode::PARALLEL); | |
| 649 | 661 |
| 650 // Post tasks to saturate the pool. | 662 // Post tasks to saturate the pool. |
| 651 std::vector<std::unique_ptr<WaitableEvent>> task_started_events; | 663 std::vector<std::unique_ptr<WaitableEvent>> task_started_events; |
| 652 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { | 664 for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) { |
| 653 task_started_events.push_back( | 665 task_started_events.push_back( |
| 654 MakeUnique<WaitableEvent>(WaitableEvent::ResetPolicy::MANUAL, | 666 MakeUnique<WaitableEvent>(WaitableEvent::ResetPolicy::MANUAL, |
| 655 WaitableEvent::InitialState::NOT_SIGNALED)); | 667 WaitableEvent::InitialState::NOT_SIGNALED)); |
| 656 task_runner->PostTask( | 668 task_runner->PostTask( |
| 657 FROM_HERE, | 669 FROM_HERE, |
| 658 Bind(&SignalAndWaitEvent, Unretained(task_started_events.back().get()), | 670 Bind(&SignalAndWaitEvent, Unretained(task_started_events.back().get()), |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 714 void VerifyThreadIdIsNot(PlatformThreadId thread_id) { | 726 void VerifyThreadIdIsNot(PlatformThreadId thread_id) { |
| 715 EXPECT_NE(thread_id, PlatformThread::CurrentId()); | 727 EXPECT_NE(thread_id, PlatformThread::CurrentId()); |
| 716 } | 728 } |
| 717 | 729 |
| 718 } // namespace | 730 } // namespace |
| 719 | 731 |
| 720 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeDetach) { | 732 TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeDetach) { |
| 721 InitializeWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); | 733 InitializeWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); |
| 722 | 734 |
| 723 // This test assumes that the TaskRunners aren't assigned to the same worker. | 735 // This test assumes that the TaskRunners aren't assigned to the same worker. |
| 724 auto task_runner = worker_pool_->CreateTaskRunnerWithTraits( | 736 auto task_runner = |
| 725 TaskTraits(), ExecutionMode::SINGLE_THREADED); | 737 worker_pool_->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()); |
| 726 auto other_task_runner = worker_pool_->CreateTaskRunnerWithTraits( | 738 auto other_task_runner = |
| 727 TaskTraits(), ExecutionMode::SINGLE_THREADED); | 739 worker_pool_->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()); |
| 728 | 740 |
| 729 // Post 3 tasks and wait until they run. | 741 // Post 3 tasks and wait until they run. |
| 730 PlatformThreadId thread_id; | 742 PlatformThreadId thread_id; |
| 731 task_runner->PostTask(FROM_HERE, | 743 task_runner->PostTask(FROM_HERE, |
| 732 Bind(&CaptureThreadId, Unretained(&thread_id))); | 744 Bind(&CaptureThreadId, Unretained(&thread_id))); |
| 733 task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); | 745 task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); |
| 734 task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); | 746 task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); |
| 735 worker_pool_->WaitForAllWorkersIdleForTesting(); | 747 worker_pool_->WaitForAllWorkersIdleForTesting(); |
| 736 | 748 |
| 737 // To allow the SchedulerWorker associated with |task_runner| to detach: | 749 // To allow the SchedulerWorker associated with |task_runner| to detach: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 748 | 760 |
| 749 // Verify that counts were recorded to the histogram as expected. | 761 // Verify that counts were recorded to the histogram as expected. |
| 750 const auto* histogram = worker_pool_->num_tasks_before_detach_histogram(); | 762 const auto* histogram = worker_pool_->num_tasks_before_detach_histogram(); |
| 751 EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0)); | 763 EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0)); |
| 752 EXPECT_EQ(1, histogram->SnapshotSamples()->GetCount(3)); | 764 EXPECT_EQ(1, histogram->SnapshotSamples()->GetCount(3)); |
| 753 EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10)); | 765 EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10)); |
| 754 } | 766 } |
| 755 | 767 |
| 756 } // namespace internal | 768 } // namespace internal |
| 757 } // namespace base | 769 } // namespace base |
| OLD | NEW |