Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/threading/sequenced_worker_pool.h" | 5 #include "base/threading/sequenced_worker_pool.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <memory> | 10 #include <memory> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
| 14 #include "base/macros.h" | 14 #include "base/macros.h" |
| 15 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
| 16 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
| 17 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
| 18 #include "base/synchronization/condition_variable.h" | 18 #include "base/synchronization/condition_variable.h" |
| 19 #include "base/synchronization/lock.h" | 19 #include "base/synchronization/lock.h" |
| 20 #include "base/task_scheduler/scheduler_worker_pool_params.h" | |
| 21 #include "base/task_scheduler/task_scheduler.h" | |
| 22 #include "base/task_scheduler/task_scheduler_impl.h" | |
| 20 #include "base/test/sequenced_task_runner_test_template.h" | 23 #include "base/test/sequenced_task_runner_test_template.h" |
| 21 #include "base/test/sequenced_worker_pool_owner.h" | 24 #include "base/test/sequenced_worker_pool_owner.h" |
| 22 #include "base/test/task_runner_test_template.h" | 25 #include "base/test/task_runner_test_template.h" |
| 23 #include "base/test/test_timeouts.h" | 26 #include "base/test/test_timeouts.h" |
| 24 #include "base/threading/platform_thread.h" | 27 #include "base/threading/platform_thread.h" |
| 25 #include "base/time/time.h" | 28 #include "base/time/time.h" |
| 26 #include "base/tracked_objects.h" | 29 #include "base/tracked_objects.h" |
| 27 #include "testing/gtest/include/gtest/gtest.h" | 30 #include "testing/gtest/include/gtest/gtest.h" |
| 28 | 31 |
| 29 namespace base { | 32 namespace base { |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 224 | 227 |
| 225 base::ConditionVariable cond_var_; | 228 base::ConditionVariable cond_var_; |
| 226 | 229 |
| 227 // Protected by lock_. | 230 // Protected by lock_. |
| 228 std::vector<int> complete_sequence_; | 231 std::vector<int> complete_sequence_; |
| 229 | 232 |
| 230 // Counter of the number of "block" workers that have started. | 233 // Counter of the number of "block" workers that have started. |
| 231 size_t started_events_; | 234 size_t started_events_; |
| 232 }; | 235 }; |
| 233 | 236 |
| 234 class SequencedWorkerPoolTest : public testing::Test { | 237 enum class SequencedWorkerPoolRedirection { NONE, TO_TASK_SCHEDULER }; |
| 238 | |
| 239 class SequencedWorkerPoolTest | |
| 240 : public testing::TestWithParam<SequencedWorkerPoolRedirection> { | |
| 235 public: | 241 public: |
| 236 SequencedWorkerPoolTest() | 242 SequencedWorkerPoolTest() |
| 237 : tracker_(new TestTracker) { | 243 : pool_owner_(new SequencedWorkerPoolOwner(kNumWorkerThreads, "test")), |
| 238 ResetPool(); | 244 tracker_(new TestTracker) {} |
| 245 | |
| 246 void SetUp() override { | |
| 247 if (GetParam() == SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER) { | |
| 248 std::vector<SchedulerWorkerPoolParams> worker_pool_params; | |
| 249 worker_pool_params.emplace_back( | |
| 250 "SchedulerWorkerPoolName", ThreadPriority::NORMAL, | |
| 251 SchedulerWorkerPoolParams::IORestriction::ALLOWED, kNumWorkerThreads, | |
| 252 TimeDelta::Max()); | |
| 253 TaskScheduler::CreateAndSetDefaultTaskScheduler( | |
| 254 std::move(worker_pool_params), | |
| 255 base::Bind([](const TaskTraits&) -> size_t { return 0U; })); | |
|
danakj
2016/09/16 20:29:36
do you need the -> size_t here? something like it
fdoray
2016/09/16 21:21:31
doesn't compile without the -> size_t
| |
| 256 SequencedWorkerPool::ResetRedirectToTaskSchedulerForProcessForTesting(); | |
| 257 SequencedWorkerPool::RedirectToTaskSchedulerForProcess(); | |
| 258 } | |
| 259 } | |
| 260 | |
| 261 void TearDown() override { | |
| 262 // Destroy the SequencedWorkerPool before the TaskScheduler. | |
|
danakj
2016/09/16 20:29:36
say why instead of just what
fdoray
2016/09/16 21:21:31
Done.
| |
| 263 DeletePool(); | |
| 264 | |
| 265 if (GetParam() == SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER) { | |
| 266 SequencedWorkerPool::ResetRedirectToTaskSchedulerForProcessForTesting(); | |
| 267 DeleteTaskScheduler(); | |
| 268 } | |
| 239 } | 269 } |
| 240 | 270 |
| 241 const scoped_refptr<SequencedWorkerPool>& pool() { | 271 const scoped_refptr<SequencedWorkerPool>& pool() { |
| 242 return pool_owner_->pool(); | 272 return pool_owner_->pool(); |
| 243 } | 273 } |
| 244 TestTracker* tracker() { return tracker_.get(); } | 274 TestTracker* tracker() { return tracker_.get(); } |
| 245 | 275 |
| 246 // Destroys the SequencedWorkerPool instance, blocking until it is fully shut | 276 // Destroys the SequencedWorkerPool instance, blocking until it is fully shut |
| 247 // down, and creates a new instance. | 277 // down, and creates a new instance. |
|
danakj
2016/09/16 20:29:36
comment wrong now
fdoray
2016/09/16 21:21:31
Done.
| |
| 248 void ResetPool() { | 278 void DeletePool() { pool_owner_ = nullptr; } |
|
gab
2016/09/16 20:16:10
pool_owner_.reset()
fdoray
2016/09/16 21:21:31
Done.
| |
| 249 pool_owner_.reset(new SequencedWorkerPoolOwner(kNumWorkerThreads, "test")); | 279 |
| 280 // Destroys and unregisters the registered TaskScheduler, if any. | |
| 281 void DeleteTaskScheduler() { | |
| 282 if (TaskScheduler::GetInstance()) { | |
| 283 static_cast<internal::TaskSchedulerImpl*>(TaskScheduler::GetInstance()) | |
| 284 ->JoinForTesting(); | |
|
gab
2016/09/16 20:16:10
Should we add TaskScheduler::JoinForTesting?
fdoray
2016/09/16 21:21:31
I don't think we want every test that needs a Task
| |
| 285 TaskScheduler::SetInstance(nullptr); | |
| 286 } | |
| 250 } | 287 } |
| 251 | 288 |
| 252 void SetWillWaitForShutdownCallback(const Closure& callback) { | 289 void SetWillWaitForShutdownCallback(const Closure& callback) { |
| 253 pool_owner_->SetWillWaitForShutdownCallback(callback); | 290 pool_owner_->SetWillWaitForShutdownCallback(callback); |
| 254 } | 291 } |
| 255 | 292 |
| 256 // Ensures that the given number of worker threads is created by adding | 293 // Ensures that the given number of worker threads is created by adding |
| 257 // tasks and waiting until they complete. Worker thread creation is | 294 // tasks and waiting until they complete. Worker thread creation is |
| 258 // serialized, can happen on background threads asynchronously, and doesn't | 295 // serialized, can happen on background threads asynchronously, and doesn't |
| 259 // happen any more at shutdown. This means that if a test posts a bunch of | 296 // happen any more at shutdown. This means that if a test posts a bunch of |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 319 } | 356 } |
| 320 | 357 |
| 321 private: | 358 private: |
| 322 friend class base::RefCountedThreadSafe<DeletionHelper>; | 359 friend class base::RefCountedThreadSafe<DeletionHelper>; |
| 323 virtual ~DeletionHelper() { deleted_flag_->data = true; } | 360 virtual ~DeletionHelper() { deleted_flag_->data = true; } |
| 324 | 361 |
| 325 const scoped_refptr<base::RefCountedData<bool> > deleted_flag_; | 362 const scoped_refptr<base::RefCountedData<bool> > deleted_flag_; |
| 326 DISALLOW_COPY_AND_ASSIGN(DeletionHelper); | 363 DISALLOW_COPY_AND_ASSIGN(DeletionHelper); |
| 327 }; | 364 }; |
| 328 | 365 |
| 329 void HoldPoolReference(const scoped_refptr<base::SequencedWorkerPool>& pool, | 366 void ShouldNotRun(const scoped_refptr<DeletionHelper>& helper) { |
| 330 const scoped_refptr<DeletionHelper>& helper) { | |
| 331 ADD_FAILURE() << "Should never run"; | 367 ADD_FAILURE() << "Should never run"; |
| 332 } | 368 } |
| 333 | 369 |
| 334 // Tests that delayed tasks are deleted upon shutdown of the pool. | 370 // Tests that shutdown does not wait for delayed tasks. |
| 335 TEST_F(SequencedWorkerPoolTest, DelayedTaskDuringShutdown) { | 371 TEST_P(SequencedWorkerPoolTest, DelayedTaskDuringShutdown) { |
| 336 // Post something to verify the pool is started up. | 372 // Post something to verify the pool is started up. |
| 337 EXPECT_TRUE(pool()->PostTask( | 373 EXPECT_TRUE(pool()->PostTask( |
| 338 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 1))); | 374 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 1))); |
| 339 | 375 |
| 340 scoped_refptr<base::RefCountedData<bool> > deleted_flag( | 376 scoped_refptr<base::RefCountedData<bool> > deleted_flag( |
| 341 new base::RefCountedData<bool>(false)); | 377 new base::RefCountedData<bool>(false)); |
| 342 | 378 |
| 343 base::Time posted_at(base::Time::Now()); | 379 base::Time posted_at(base::Time::Now()); |
| 344 // Post something that shouldn't run. | 380 // Post something that shouldn't run. |
| 345 EXPECT_TRUE(pool()->PostDelayedTask( | 381 EXPECT_TRUE(pool()->PostDelayedTask( |
| 346 FROM_HERE, | 382 FROM_HERE, |
| 347 base::Bind(&HoldPoolReference, | 383 base::Bind(&ShouldNotRun, |
| 348 pool(), | |
| 349 make_scoped_refptr(new DeletionHelper(deleted_flag))), | 384 make_scoped_refptr(new DeletionHelper(deleted_flag))), |
| 350 TestTimeouts::action_timeout())); | 385 TestTimeouts::action_timeout())); |
| 351 | 386 |
| 352 std::vector<int> completion_sequence = tracker()->WaitUntilTasksComplete(1); | 387 std::vector<int> completion_sequence = tracker()->WaitUntilTasksComplete(1); |
| 353 ASSERT_EQ(1u, completion_sequence.size()); | 388 ASSERT_EQ(1u, completion_sequence.size()); |
| 354 ASSERT_EQ(1, completion_sequence[0]); | 389 ASSERT_EQ(1, completion_sequence[0]); |
| 355 | 390 |
| 356 // Shutdown is asynchronous, so use ResetPool() to block until the pool is | 391 // Shutdown the pool. |
| 357 // fully destroyed (and thus shut down). | 392 pool()->Shutdown(); |
| 358 ResetPool(); | 393 if (GetParam() == SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER) |
| 394 TaskScheduler::GetInstance()->Shutdown(); | |
| 359 | 395 |
| 360 // Verify that we didn't block until the task was due. | 396 // Verify that we didn't block until the task was due. |
| 361 ASSERT_LT(base::Time::Now() - posted_at, TestTimeouts::action_timeout()); | 397 ASSERT_LT(base::Time::Now() - posted_at, TestTimeouts::action_timeout()); |
| 362 | 398 |
| 363 // Verify that the deferred task has not only not run, but has also been | 399 // Verify that the delayed task is deleted when the SequencedWorkerPool (and |
| 364 // destroyed. | 400 // the TaskScheduler when applicable) are deleted. |
| 365 ASSERT_TRUE(deleted_flag->data); | 401 EXPECT_FALSE(deleted_flag->data); |
| 402 DeletePool(); | |
| 403 if (GetParam() == SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER) | |
| 404 DeleteTaskScheduler(); | |
| 405 EXPECT_TRUE(deleted_flag->data); | |
| 366 } | 406 } |
| 367 | 407 |
| 368 // Tests that same-named tokens have the same ID. | 408 // Tests that same-named tokens have the same ID. |
| 369 TEST_F(SequencedWorkerPoolTest, NamedTokens) { | 409 TEST_P(SequencedWorkerPoolTest, NamedTokens) { |
| 370 const std::string name1("hello"); | 410 const std::string name1("hello"); |
| 371 SequencedWorkerPool::SequenceToken token1 = | 411 SequencedWorkerPool::SequenceToken token1 = |
| 372 pool()->GetNamedSequenceToken(name1); | 412 pool()->GetNamedSequenceToken(name1); |
| 373 | 413 |
| 374 SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken(); | 414 SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken(); |
| 375 | 415 |
| 376 const std::string name3("goodbye"); | 416 const std::string name3("goodbye"); |
| 377 SequencedWorkerPool::SequenceToken token3 = | 417 SequencedWorkerPool::SequenceToken token3 = |
| 378 pool()->GetNamedSequenceToken(name3); | 418 pool()->GetNamedSequenceToken(name3); |
| 379 | 419 |
| 380 // All 3 tokens should be different. | 420 // All 3 tokens should be different. |
| 381 EXPECT_FALSE(token1.Equals(token2)); | 421 EXPECT_FALSE(token1.Equals(token2)); |
| 382 EXPECT_FALSE(token1.Equals(token3)); | 422 EXPECT_FALSE(token1.Equals(token3)); |
| 383 EXPECT_FALSE(token2.Equals(token3)); | 423 EXPECT_FALSE(token2.Equals(token3)); |
| 384 | 424 |
| 385 // Requesting the same name again should give the same value. | 425 // Requesting the same name again should give the same value. |
| 386 SequencedWorkerPool::SequenceToken token1again = | 426 SequencedWorkerPool::SequenceToken token1again = |
| 387 pool()->GetNamedSequenceToken(name1); | 427 pool()->GetNamedSequenceToken(name1); |
| 388 EXPECT_TRUE(token1.Equals(token1again)); | 428 EXPECT_TRUE(token1.Equals(token1again)); |
| 389 | 429 |
| 390 SequencedWorkerPool::SequenceToken token3again = | 430 SequencedWorkerPool::SequenceToken token3again = |
| 391 pool()->GetNamedSequenceToken(name3); | 431 pool()->GetNamedSequenceToken(name3); |
| 392 EXPECT_TRUE(token3.Equals(token3again)); | 432 EXPECT_TRUE(token3.Equals(token3again)); |
| 393 } | 433 } |
| 394 | 434 |
| 395 // Tests that posting a bunch of tasks (many more than the number of worker | 435 // Tests that posting a bunch of tasks (many more than the number of worker |
| 396 // threads) runs them all. | 436 // threads) runs them all. |
| 397 TEST_F(SequencedWorkerPoolTest, LotsOfTasks) { | 437 TEST_P(SequencedWorkerPoolTest, LotsOfTasks) { |
| 398 pool()->PostWorkerTask(FROM_HERE, | 438 pool()->PostWorkerTask(FROM_HERE, |
| 399 base::Bind(&TestTracker::SlowTask, tracker(), 0)); | 439 base::Bind(&TestTracker::SlowTask, tracker(), 0)); |
| 400 | 440 |
| 401 const size_t kNumTasks = 20; | 441 const size_t kNumTasks = 20; |
| 402 for (size_t i = 1; i < kNumTasks; i++) { | 442 for (size_t i = 1; i < kNumTasks; i++) { |
| 403 pool()->PostWorkerTask(FROM_HERE, | 443 pool()->PostWorkerTask(FROM_HERE, |
| 404 base::Bind(&TestTracker::FastTask, tracker(), i)); | 444 base::Bind(&TestTracker::FastTask, tracker(), i)); |
| 405 } | 445 } |
| 406 | 446 |
| 407 std::vector<int> result = tracker()->WaitUntilTasksComplete(kNumTasks); | 447 std::vector<int> result = tracker()->WaitUntilTasksComplete(kNumTasks); |
| 408 EXPECT_EQ(kNumTasks, result.size()); | 448 EXPECT_EQ(kNumTasks, result.size()); |
| 409 } | 449 } |
| 410 | 450 |
| 411 // Tests that posting a bunch of tasks (many more than the number of | 451 // Tests that posting a bunch of tasks (many more than the number of |
| 412 // worker threads) to two pools simultaneously runs them all twice. | 452 // worker threads) to two pools simultaneously runs them all twice. |
| 413 // This test is meant to shake out any concurrency issues between | 453 // This test is meant to shake out any concurrency issues between |
| 414 // pools (like histograms). | 454 // pools (like histograms). |
| 415 TEST_F(SequencedWorkerPoolTest, LotsOfTasksTwoPools) { | 455 TEST_P(SequencedWorkerPoolTest, LotsOfTasksTwoPools) { |
| 416 SequencedWorkerPoolOwner pool1(kNumWorkerThreads, "test1"); | 456 SequencedWorkerPoolOwner pool1(kNumWorkerThreads, "test1"); |
| 417 SequencedWorkerPoolOwner pool2(kNumWorkerThreads, "test2"); | 457 SequencedWorkerPoolOwner pool2(kNumWorkerThreads, "test2"); |
| 418 | 458 |
| 419 base::Closure slow_task = base::Bind(&TestTracker::SlowTask, tracker(), 0); | 459 base::Closure slow_task = base::Bind(&TestTracker::SlowTask, tracker(), 0); |
| 420 pool1.pool()->PostWorkerTask(FROM_HERE, slow_task); | 460 pool1.pool()->PostWorkerTask(FROM_HERE, slow_task); |
| 421 pool2.pool()->PostWorkerTask(FROM_HERE, slow_task); | 461 pool2.pool()->PostWorkerTask(FROM_HERE, slow_task); |
| 422 | 462 |
| 423 const size_t kNumTasks = 20; | 463 const size_t kNumTasks = 20; |
| 424 for (size_t i = 1; i < kNumTasks; i++) { | 464 for (size_t i = 1; i < kNumTasks; i++) { |
| 425 base::Closure fast_task = | 465 base::Closure fast_task = |
| 426 base::Bind(&TestTracker::FastTask, tracker(), i); | 466 base::Bind(&TestTracker::FastTask, tracker(), i); |
| 427 pool1.pool()->PostWorkerTask(FROM_HERE, fast_task); | 467 pool1.pool()->PostWorkerTask(FROM_HERE, fast_task); |
| 428 pool2.pool()->PostWorkerTask(FROM_HERE, fast_task); | 468 pool2.pool()->PostWorkerTask(FROM_HERE, fast_task); |
| 429 } | 469 } |
| 430 | 470 |
| 431 std::vector<int> result = | 471 std::vector<int> result = |
| 432 tracker()->WaitUntilTasksComplete(2*kNumTasks); | 472 tracker()->WaitUntilTasksComplete(2*kNumTasks); |
| 433 EXPECT_EQ(2 * kNumTasks, result.size()); | 473 EXPECT_EQ(2 * kNumTasks, result.size()); |
| 434 } | 474 } |
| 435 | 475 |
| 436 // Test that tasks with the same sequence token are executed in order but don't | 476 // Test that tasks with the same sequence token are executed in order but don't |
| 437 // affect other tasks. | 477 // affect other tasks. |
| 438 TEST_F(SequencedWorkerPoolTest, Sequence) { | 478 TEST_P(SequencedWorkerPoolTest, Sequence) { |
| 439 // Fill all the worker threads except one. | 479 // Fill all the worker threads except one. |
| 440 const size_t kNumBackgroundTasks = kNumWorkerThreads - 1; | 480 const size_t kNumBackgroundTasks = kNumWorkerThreads - 1; |
| 441 ThreadBlocker background_blocker; | 481 ThreadBlocker background_blocker; |
| 442 for (size_t i = 0; i < kNumBackgroundTasks; i++) { | 482 for (size_t i = 0; i < kNumBackgroundTasks; i++) { |
| 443 pool()->PostWorkerTask(FROM_HERE, | 483 pool()->PostWorkerTask(FROM_HERE, |
| 444 base::Bind(&TestTracker::BlockTask, | 484 base::Bind(&TestTracker::BlockTask, |
| 445 tracker(), i, &background_blocker)); | 485 tracker(), i, &background_blocker)); |
| 446 } | 486 } |
| 447 tracker()->WaitUntilTasksBlocked(kNumBackgroundTasks); | 487 tracker()->WaitUntilTasksBlocked(kNumBackgroundTasks); |
| 448 | 488 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 489 // Allow the first task of token1 to complete. This should run the second. | 529 // Allow the first task of token1 to complete. This should run the second. |
| 490 blocker.Unblock(1); | 530 blocker.Unblock(1); |
| 491 result = tracker()->WaitUntilTasksComplete(kNumBackgroundTasks + 4); | 531 result = tracker()->WaitUntilTasksComplete(kNumBackgroundTasks + 4); |
| 492 ASSERT_EQ(kNumBackgroundTasks + 4, result.size()); | 532 ASSERT_EQ(kNumBackgroundTasks + 4, result.size()); |
| 493 EXPECT_EQ(100, result[result.size() - 2]); | 533 EXPECT_EQ(100, result[result.size() - 2]); |
| 494 EXPECT_EQ(101, result[result.size() - 1]); | 534 EXPECT_EQ(101, result[result.size() - 1]); |
| 495 } | 535 } |
| 496 | 536 |
| 497 // Tests that any tasks posted after Shutdown are ignored. | 537 // Tests that any tasks posted after Shutdown are ignored. |
| 498 // Disabled for flakiness. See http://crbug.com/166451. | 538 // Disabled for flakiness. See http://crbug.com/166451. |
| 499 TEST_F(SequencedWorkerPoolTest, DISABLED_IgnoresAfterShutdown) { | 539 TEST_P(SequencedWorkerPoolTest, DISABLED_IgnoresAfterShutdown) { |
| 500 // Start tasks to take all the threads and block them. | 540 // Start tasks to take all the threads and block them. |
| 501 EnsureAllWorkersCreated(); | 541 EnsureAllWorkersCreated(); |
| 502 ThreadBlocker blocker; | 542 ThreadBlocker blocker; |
| 503 for (size_t i = 0; i < kNumWorkerThreads; i++) { | 543 for (size_t i = 0; i < kNumWorkerThreads; i++) { |
| 504 pool()->PostWorkerTask(FROM_HERE, | 544 pool()->PostWorkerTask(FROM_HERE, |
| 505 base::Bind(&TestTracker::BlockTask, | 545 base::Bind(&TestTracker::BlockTask, |
| 506 tracker(), i, &blocker)); | 546 tracker(), i, &blocker)); |
| 507 } | 547 } |
| 508 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); | 548 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); |
| 509 | 549 |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 536 base::Bind(&TestTracker::FastTask, tracker(), 101), | 576 base::Bind(&TestTracker::FastTask, tracker(), 101), |
| 537 SequencedWorkerPool::SKIP_ON_SHUTDOWN)); | 577 SequencedWorkerPool::SKIP_ON_SHUTDOWN)); |
| 538 EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( | 578 EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( |
| 539 FROM_HERE, | 579 FROM_HERE, |
| 540 base::Bind(&TestTracker::FastTask, tracker(), 102), | 580 base::Bind(&TestTracker::FastTask, tracker(), 102), |
| 541 SequencedWorkerPool::BLOCK_SHUTDOWN)); | 581 SequencedWorkerPool::BLOCK_SHUTDOWN)); |
| 542 | 582 |
| 543 ASSERT_EQ(old_has_work_call_count, has_work_call_count()); | 583 ASSERT_EQ(old_has_work_call_count, has_work_call_count()); |
| 544 } | 584 } |
| 545 | 585 |
| 546 TEST_F(SequencedWorkerPoolTest, AllowsAfterShutdown) { | 586 TEST_P(SequencedWorkerPoolTest, AllowsAfterShutdown) { |
| 587 // As tested by TaskSchedulerTaskTrackerTest.WillPostAndRunDuringShutdown, | |
| 588 // TaskScheduler allows tasks to be posted during shutdown. However, since it | |
| 589 // doesn't provide a way to run a callback from inside its Shutdown() method, | |
| 590 // it would be hard to make this test work with redirection enabled. | |
| 591 if (GetParam() == SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER) | |
| 592 return; | |
| 593 | |
| 547 // Test that <n> new blocking tasks are allowed provided they're posted | 594 // Test that <n> new blocking tasks are allowed provided they're posted |
| 548 // by a running tasks. | 595 // by a running tasks. |
| 549 EnsureAllWorkersCreated(); | 596 EnsureAllWorkersCreated(); |
| 550 ThreadBlocker blocker; | 597 ThreadBlocker blocker; |
| 551 | 598 |
| 552 // Start tasks to take all the threads and block them. | 599 // Start tasks to take all the threads and block them. |
| 553 const int kNumBlockTasks = static_cast<int>(kNumWorkerThreads); | 600 const int kNumBlockTasks = static_cast<int>(kNumWorkerThreads); |
| 554 for (int i = 0; i < kNumBlockTasks; ++i) { | 601 for (int i = 0; i < kNumBlockTasks; ++i) { |
| 555 EXPECT_TRUE(pool()->PostWorkerTask( | 602 EXPECT_TRUE(pool()->PostWorkerTask( |
| 556 FROM_HERE, | 603 FROM_HERE, |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 582 // Ensure that the correct number of tasks actually got run. | 629 // Ensure that the correct number of tasks actually got run. |
| 583 tracker()->WaitUntilTasksComplete(static_cast<size_t>( | 630 tracker()->WaitUntilTasksComplete(static_cast<size_t>( |
| 584 kNumBlockTasks + kNumQueuedTasks + kNumNewBlockingTasksToAllow)); | 631 kNumBlockTasks + kNumQueuedTasks + kNumNewBlockingTasksToAllow)); |
| 585 | 632 |
| 586 // Clean up the task IDs we added and go home. | 633 // Clean up the task IDs we added and go home. |
| 587 tracker()->ClearCompleteSequence(); | 634 tracker()->ClearCompleteSequence(); |
| 588 } | 635 } |
| 589 | 636 |
| 590 // Tests that blocking tasks can still be posted during shutdown, as long as | 637 // Tests that blocking tasks can still be posted during shutdown, as long as |
| 591 // the task is not being posted within the context of a running task. | 638 // the task is not being posted within the context of a running task. |
| 592 TEST_F(SequencedWorkerPoolTest, | 639 TEST_P(SequencedWorkerPoolTest, |
| 593 AllowsBlockingTasksDuringShutdownOutsideOfRunningTask) { | 640 AllowsBlockingTasksDuringShutdownOutsideOfRunningTask) { |
| 641 // As tested by TaskSchedulerTaskTrackerTest.WillPostAndRunDuringShutdown, | |
| 642 // TaskScheduler allows tasks to be posted during shutdown. However, since it | |
| 643 // doesn't provide a way to run a callback from inside its Shutdown() method, | |
| 644 // it would be hard to make this test work with redirection enabled. | |
| 645 if (GetParam() == SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER) | |
| 646 return; | |
| 647 | |
| 594 EnsureAllWorkersCreated(); | 648 EnsureAllWorkersCreated(); |
| 595 ThreadBlocker blocker; | 649 ThreadBlocker blocker; |
| 596 | 650 |
| 597 // Start tasks to take all the threads and block them. | 651 // Start tasks to take all the threads and block them. |
| 598 const int kNumBlockTasks = static_cast<int>(kNumWorkerThreads); | 652 const int kNumBlockTasks = static_cast<int>(kNumWorkerThreads); |
| 599 for (int i = 0; i < kNumBlockTasks; ++i) { | 653 for (int i = 0; i < kNumBlockTasks; ++i) { |
| 600 EXPECT_TRUE(pool()->PostWorkerTask( | 654 EXPECT_TRUE(pool()->PostWorkerTask( |
| 601 FROM_HERE, | 655 FROM_HERE, |
| 602 base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker))); | 656 base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker))); |
| 603 } | 657 } |
| 604 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); | 658 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); |
| 605 | 659 |
| 606 // Setup to open the floodgates from within Shutdown(). | 660 // Setup to open the floodgates from within Shutdown(). |
| 607 SetWillWaitForShutdownCallback( | 661 SetWillWaitForShutdownCallback( |
| 608 base::Bind(&TestTracker::PostBlockingTaskThenUnblockThreads, | 662 base::Bind(&TestTracker::PostBlockingTaskThenUnblockThreads, |
| 609 scoped_refptr<TestTracker>(tracker()), pool(), &blocker, | 663 scoped_refptr<TestTracker>(tracker()), pool(), &blocker, |
| 610 kNumWorkerThreads)); | 664 kNumWorkerThreads)); |
| 611 pool()->Shutdown(kNumWorkerThreads + 1); | 665 pool()->Shutdown(kNumWorkerThreads + 1); |
| 612 | 666 |
| 613 // Ensure that the correct number of tasks actually got run. | 667 // Ensure that the correct number of tasks actually got run. |
| 614 tracker()->WaitUntilTasksComplete(static_cast<size_t>(kNumWorkerThreads + 1)); | 668 tracker()->WaitUntilTasksComplete(static_cast<size_t>(kNumWorkerThreads + 1)); |
| 615 tracker()->ClearCompleteSequence(); | 669 tracker()->ClearCompleteSequence(); |
| 616 } | 670 } |
| 617 | 671 |
| 618 // Tests that unrun tasks are discarded properly according to their shutdown | 672 // Tests that unrun tasks are discarded properly according to their shutdown |
| 619 // mode. | 673 // mode. |
| 620 TEST_F(SequencedWorkerPoolTest, DiscardOnShutdown) { | 674 TEST_P(SequencedWorkerPoolTest, DiscardOnShutdown) { |
| 675 // As tested by | |
| 676 // TaskSchedulerTaskTrackerTest.WillPostBeforeShutdownRunDuringShutdown, on | |
| 677 // shutdown, the TaskScheduler discards SKIP_ON_SHUTDOWN and | |
| 678 // CONTINUE_ON_SHUTDOWN tasks and runs BLOCK_SHUTDOWN tasks. However, since it | |
| 679 // doesn't provide a way to run a callback from inside its Shutdown() method, | |
| 680 // it would be hard to make this test work with redirection enabled. | |
| 681 if (GetParam() == SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER) | |
| 682 return; | |
| 683 | |
| 621 // Start tasks to take all the threads and block them. | 684 // Start tasks to take all the threads and block them. |
| 622 EnsureAllWorkersCreated(); | 685 EnsureAllWorkersCreated(); |
| 623 ThreadBlocker blocker; | 686 ThreadBlocker blocker; |
| 624 for (size_t i = 0; i < kNumWorkerThreads; i++) { | 687 for (size_t i = 0; i < kNumWorkerThreads; i++) { |
| 625 pool()->PostWorkerTask(FROM_HERE, | 688 pool()->PostWorkerTask(FROM_HERE, |
| 626 base::Bind(&TestTracker::BlockTask, | 689 base::Bind(&TestTracker::BlockTask, |
| 627 tracker(), i, &blocker)); | 690 tracker(), i, &blocker)); |
| 628 } | 691 } |
| 629 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); | 692 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); |
| 630 | 693 |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 654 | 717 |
| 655 // The kNumWorkerThread items should have completed, plus the BLOCK_SHUTDOWN | 718 // The kNumWorkerThread items should have completed, plus the BLOCK_SHUTDOWN |
| 656 // one, in no particular order. | 719 // one, in no particular order. |
| 657 ASSERT_EQ(kNumWorkerThreads + 1, result.size()); | 720 ASSERT_EQ(kNumWorkerThreads + 1, result.size()); |
| 658 for (size_t i = 0; i < kNumWorkerThreads; i++) | 721 for (size_t i = 0; i < kNumWorkerThreads; i++) |
| 659 EXPECT_TRUE(ContainsValue(result, static_cast<int>(i))); | 722 EXPECT_TRUE(ContainsValue(result, static_cast<int>(i))); |
| 660 EXPECT_TRUE(ContainsValue(result, 102)); | 723 EXPECT_TRUE(ContainsValue(result, 102)); |
| 661 } | 724 } |
| 662 | 725 |
| 663 // Tests that CONTINUE_ON_SHUTDOWN tasks don't block shutdown. | 726 // Tests that CONTINUE_ON_SHUTDOWN tasks don't block shutdown. |
| 664 TEST_F(SequencedWorkerPoolTest, ContinueOnShutdown) { | 727 TEST_P(SequencedWorkerPoolTest, ContinueOnShutdown) { |
| 665 scoped_refptr<TaskRunner> runner(pool()->GetTaskRunnerWithShutdownBehavior( | 728 scoped_refptr<TaskRunner> runner(pool()->GetTaskRunnerWithShutdownBehavior( |
| 666 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); | 729 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); |
| 667 scoped_refptr<SequencedTaskRunner> sequenced_runner( | 730 scoped_refptr<SequencedTaskRunner> sequenced_runner( |
| 668 pool()->GetSequencedTaskRunnerWithShutdownBehavior( | 731 pool()->GetSequencedTaskRunnerWithShutdownBehavior( |
| 669 pool()->GetSequenceToken(), | 732 pool()->GetSequenceToken(), |
| 670 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); | 733 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); |
| 671 EnsureAllWorkersCreated(); | 734 EnsureAllWorkersCreated(); |
| 672 ThreadBlocker blocker; | 735 ThreadBlocker blocker; |
| 673 pool()->PostWorkerTaskWithShutdownBehavior( | 736 pool()->PostWorkerTaskWithShutdownBehavior( |
| 674 FROM_HERE, | 737 FROM_HERE, |
| 675 base::Bind(&TestTracker::BlockTask, | 738 base::Bind(&TestTracker::BlockTask, |
| 676 tracker(), 0, &blocker), | 739 tracker(), 0, &blocker), |
| 677 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); | 740 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); |
| 678 runner->PostTask( | 741 runner->PostTask( |
| 679 FROM_HERE, | 742 FROM_HERE, |
| 680 base::Bind(&TestTracker::BlockTask, | 743 base::Bind(&TestTracker::BlockTask, |
| 681 tracker(), 1, &blocker)); | 744 tracker(), 1, &blocker)); |
| 682 sequenced_runner->PostTask( | 745 sequenced_runner->PostTask( |
| 683 FROM_HERE, | 746 FROM_HERE, |
| 684 base::Bind(&TestTracker::BlockTask, | 747 base::Bind(&TestTracker::BlockTask, |
| 685 tracker(), 2, &blocker)); | 748 tracker(), 2, &blocker)); |
| 686 | 749 |
| 687 tracker()->WaitUntilTasksBlocked(3); | 750 tracker()->WaitUntilTasksBlocked(3); |
| 688 | 751 |
| 689 // This should not block. If this test hangs, it means it failed. | 752 // This should not block. If this test hangs, it means it failed. |
| 690 pool()->Shutdown(); | 753 pool()->Shutdown(); |
| 754 if (GetParam() == SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER) | |
| 755 TaskScheduler::GetInstance()->Shutdown(); | |
| 691 | 756 |
| 692 // The task should not have completed yet. | 757 // The task should not have completed yet. |
| 693 EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size()); | 758 EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size()); |
| 694 | 759 |
| 695 // Posting more tasks should fail. | 760 // Posting more tasks should fail. |
| 696 EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( | 761 EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( |
| 697 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0), | 762 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0), |
| 698 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); | 763 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); |
| 699 EXPECT_FALSE(runner->PostTask( | 764 EXPECT_FALSE(runner->PostTask( |
| 700 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0))); | 765 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0))); |
| 701 EXPECT_FALSE(sequenced_runner->PostTask( | 766 EXPECT_FALSE(sequenced_runner->PostTask( |
| 702 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0))); | 767 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0))); |
| 703 | 768 |
| 704 // Continue the background thread and make sure the tasks can complete. | 769 // Continue the background thread and make sure the tasks can complete. |
| 705 blocker.Unblock(3); | 770 blocker.Unblock(3); |
| 706 std::vector<int> result = tracker()->WaitUntilTasksComplete(3); | 771 std::vector<int> result = tracker()->WaitUntilTasksComplete(3); |
| 707 EXPECT_EQ(3u, result.size()); | 772 EXPECT_EQ(3u, result.size()); |
| 708 } | 773 } |
| 709 | 774 |
| 710 // Tests that SKIP_ON_SHUTDOWN tasks that have been started block Shutdown | 775 // Tests that SKIP_ON_SHUTDOWN tasks that have been started block Shutdown |
| 711 // until they stop, but tasks not yet started do not. | 776 // until they stop, but tasks not yet started do not. |
| 712 TEST_F(SequencedWorkerPoolTest, SkipOnShutdown) { | 777 TEST_P(SequencedWorkerPoolTest, SkipOnShutdown) { |
| 778 // As tested by | |
| 779 // TaskSchedulerTaskTrackerTest.WillPostAndRunLongTaskBeforeShutdown and | |
| 780 // TaskSchedulerTaskTrackerTest.WillPostBeforeShutdownRunDuringShutdown, the | |
| 781 // TaskScheduler correctly handles SKIP_ON_SHUTDOWN tasks. However, since it | |
| 782 // doesn't provide a way to run a callback from inside its Shutdown() method, | |
| 783 // it would be hard to make this test work with redirection enabled. | |
| 784 if (GetParam() == SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER) | |
| 785 return; | |
| 786 | |
| 713 // Start tasks to take all the threads and block them. | 787 // Start tasks to take all the threads and block them. |
| 714 EnsureAllWorkersCreated(); | 788 EnsureAllWorkersCreated(); |
| 715 ThreadBlocker blocker; | 789 ThreadBlocker blocker; |
| 716 | 790 |
| 717 // Now block all the threads with SKIP_ON_SHUTDOWN. Shutdown() should not | 791 // Now block all the threads with SKIP_ON_SHUTDOWN. Shutdown() should not |
| 718 // return until these tasks have completed. | 792 // return until these tasks have completed. |
| 719 for (size_t i = 0; i < kNumWorkerThreads; i++) { | 793 for (size_t i = 0; i < kNumWorkerThreads; i++) { |
| 720 pool()->PostWorkerTaskWithShutdownBehavior( | 794 pool()->PostWorkerTaskWithShutdownBehavior( |
| 721 FROM_HERE, | 795 FROM_HERE, |
| 722 base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker), | 796 base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker), |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 753 // allowed to complete. No additional non-blocking tasks should have been | 827 // allowed to complete. No additional non-blocking tasks should have been |
| 754 // started. | 828 // started. |
| 755 ASSERT_EQ(kNumWorkerThreads, result.size()); | 829 ASSERT_EQ(kNumWorkerThreads, result.size()); |
| 756 for (size_t i = 0; i < kNumWorkerThreads; i++) | 830 for (size_t i = 0; i < kNumWorkerThreads; i++) |
| 757 EXPECT_TRUE(ContainsValue(result, static_cast<int>(i))); | 831 EXPECT_TRUE(ContainsValue(result, static_cast<int>(i))); |
| 758 } | 832 } |
| 759 | 833 |
| 760 // Ensure all worker threads are created, and then trigger a spurious | 834 // Ensure all worker threads are created, and then trigger a spurious |
| 761 // work signal. This shouldn't cause any other work signals to be | 835 // work signal. This shouldn't cause any other work signals to be |
| 762 // triggered. This is a regression test for http://crbug.com/117469. | 836 // triggered. This is a regression test for http://crbug.com/117469. |
| 763 TEST_F(SequencedWorkerPoolTest, SpuriousWorkSignal) { | 837 TEST_P(SequencedWorkerPoolTest, SpuriousWorkSignal) { |
| 838 // This test doesn't apply when tasks are redirected to the TaskScheduler. | |
| 839 if (GetParam() == SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER) | |
| 840 return; | |
| 841 | |
| 764 EnsureAllWorkersCreated(); | 842 EnsureAllWorkersCreated(); |
| 765 int old_has_work_call_count = has_work_call_count(); | 843 int old_has_work_call_count = has_work_call_count(); |
| 766 pool()->SignalHasWorkForTesting(); | 844 pool()->SignalHasWorkForTesting(); |
| 767 // This is inherently racy, but can only produce false positives. | 845 // This is inherently racy, but can only produce false positives. |
| 768 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); | 846 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); |
| 769 EXPECT_EQ(old_has_work_call_count + 1, has_work_call_count()); | 847 EXPECT_EQ(old_has_work_call_count + 1, has_work_call_count()); |
| 770 } | 848 } |
| 771 | 849 |
| 772 void VerifyRunsTasksOnCurrentThread( | 850 void VerifyRunsTasksOnCurrentThread( |
| 851 SequencedWorkerPoolRedirection redirection, | |
| 773 scoped_refptr<TaskRunner> test_positive_task_runner, | 852 scoped_refptr<TaskRunner> test_positive_task_runner, |
| 774 scoped_refptr<TaskRunner> test_negative_task_runner, | 853 scoped_refptr<TaskRunner> test_negative_task_runner, |
| 775 SequencedWorkerPool* pool, | 854 SequencedWorkerPool* pool, |
| 776 SequencedWorkerPool* unused_pool) { | 855 SequencedWorkerPool* unused_pool) { |
| 777 EXPECT_TRUE(test_positive_task_runner->RunsTasksOnCurrentThread()); | 856 EXPECT_TRUE(test_positive_task_runner->RunsTasksOnCurrentThread()); |
| 778 EXPECT_FALSE(test_negative_task_runner->RunsTasksOnCurrentThread()); | 857 EXPECT_FALSE(test_negative_task_runner->RunsTasksOnCurrentThread()); |
| 779 EXPECT_TRUE(pool->RunsTasksOnCurrentThread()); | 858 EXPECT_TRUE(pool->RunsTasksOnCurrentThread()); |
| 780 EXPECT_FALSE(unused_pool->RunsTasksOnCurrentThread()); | 859 |
| 860 // Tasks posted to different SequencedWorkerPools may run on the same | |
| 861 // TaskScheduler threads. | |
| 862 if (redirection == SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER) | |
| 863 EXPECT_TRUE(unused_pool->RunsTasksOnCurrentThread()); | |
| 864 else | |
| 865 EXPECT_FALSE(unused_pool->RunsTasksOnCurrentThread()); | |
| 781 } | 866 } |
| 782 | 867 |
| 783 // Verify correctness of the RunsTasksOnCurrentThread() method on | 868 // Verify correctness of the RunsTasksOnCurrentThread() method on |
| 784 // SequencedWorkerPool and on TaskRunners it returns. | 869 // SequencedWorkerPool and on TaskRunners it returns. |
| 785 TEST_F(SequencedWorkerPoolTest, RunsTasksOnCurrentThread) { | 870 TEST_P(SequencedWorkerPoolTest, RunsTasksOnCurrentThread) { |
| 786 const scoped_refptr<SequencedTaskRunner> sequenced_task_runner_1 = | 871 const scoped_refptr<SequencedTaskRunner> sequenced_task_runner_1 = |
| 787 pool()->GetSequencedTaskRunner(SequencedWorkerPool::GetSequenceToken()); | 872 pool()->GetSequencedTaskRunner(SequencedWorkerPool::GetSequenceToken()); |
| 788 const scoped_refptr<SequencedTaskRunner> sequenced_task_runner_2 = | 873 const scoped_refptr<SequencedTaskRunner> sequenced_task_runner_2 = |
| 789 pool()->GetSequencedTaskRunner(SequencedWorkerPool::GetSequenceToken()); | 874 pool()->GetSequencedTaskRunner(SequencedWorkerPool::GetSequenceToken()); |
| 790 const scoped_refptr<TaskRunner> unsequenced_task_runner = | 875 const scoped_refptr<TaskRunner> unsequenced_task_runner = |
| 791 pool()->GetTaskRunnerWithShutdownBehavior( | 876 pool()->GetTaskRunnerWithShutdownBehavior( |
| 792 SequencedWorkerPool::BLOCK_SHUTDOWN); | 877 SequencedWorkerPool::BLOCK_SHUTDOWN); |
| 793 | 878 |
| 794 SequencedWorkerPoolOwner unused_pool_owner(2, "unused_pool"); | 879 SequencedWorkerPoolOwner unused_pool_owner(2, "unused_pool"); |
| 795 | 880 |
| 796 EXPECT_FALSE(pool()->RunsTasksOnCurrentThread()); | 881 EXPECT_FALSE(pool()->RunsTasksOnCurrentThread()); |
| 797 EXPECT_FALSE(sequenced_task_runner_1->RunsTasksOnCurrentThread()); | 882 EXPECT_FALSE(sequenced_task_runner_1->RunsTasksOnCurrentThread()); |
| 798 EXPECT_FALSE(sequenced_task_runner_2->RunsTasksOnCurrentThread()); | 883 EXPECT_FALSE(sequenced_task_runner_2->RunsTasksOnCurrentThread()); |
| 799 EXPECT_FALSE(unsequenced_task_runner->RunsTasksOnCurrentThread()); | 884 EXPECT_FALSE(unsequenced_task_runner->RunsTasksOnCurrentThread()); |
| 800 EXPECT_FALSE(unused_pool_owner.pool()->RunsTasksOnCurrentThread()); | 885 EXPECT_FALSE(unused_pool_owner.pool()->RunsTasksOnCurrentThread()); |
| 801 | 886 |
| 802 // From a task posted to |sequenced_task_runner_1|: | 887 // From a task posted to |sequenced_task_runner_1|: |
| 803 // - sequenced_task_runner_1->RunsTasksOnCurrentThread() returns true. | 888 // - sequenced_task_runner_1->RunsTasksOnCurrentThread() returns true. |
| 804 // - sequenced_task_runner_2->RunsTasksOnCurrentThread() returns false. | 889 // - sequenced_task_runner_2->RunsTasksOnCurrentThread() returns false. |
| 805 // - pool()->RunsTasksOnCurrentThread() returns true. | 890 // - pool()->RunsTasksOnCurrentThread() returns true. |
| 806 // - unused_pool_owner.pool()->RunsTasksOnCurrentThread() returns false. | 891 // - unused_pool_owner.pool()->RunsTasksOnCurrentThread() returns false. |
| 807 sequenced_task_runner_1->PostTask( | 892 sequenced_task_runner_1->PostTask( |
| 808 FROM_HERE, | 893 FROM_HERE, base::Bind(&VerifyRunsTasksOnCurrentThread, GetParam(), |
| 809 base::Bind(&VerifyRunsTasksOnCurrentThread, sequenced_task_runner_1, | 894 sequenced_task_runner_1, sequenced_task_runner_2, |
| 810 sequenced_task_runner_2, base::RetainedRef(pool()), | 895 base::RetainedRef(pool()), |
| 811 base::RetainedRef(unused_pool_owner.pool()))); | 896 base::RetainedRef(unused_pool_owner.pool()))); |
| 812 // From a task posted to |unsequenced_task_runner|: | 897 // From a task posted to |unsequenced_task_runner|: |
| 813 // - unsequenced_task_runner->RunsTasksOnCurrentThread() returns true. | 898 // - unsequenced_task_runner->RunsTasksOnCurrentThread() returns true. |
| 814 // - sequenced_task_runner_1->RunsTasksOnCurrentThread() returns false. | 899 // - sequenced_task_runner_1->RunsTasksOnCurrentThread() returns false. |
| 815 // - pool()->RunsTasksOnCurrentThread() returns true. | 900 // - pool()->RunsTasksOnCurrentThread() returns true. |
| 816 // - unused_pool_owner.pool()->RunsTasksOnCurrentThread() returns false. | 901 // - unused_pool_owner.pool()->RunsTasksOnCurrentThread() returns false. |
| 817 unsequenced_task_runner->PostTask( | 902 unsequenced_task_runner->PostTask( |
| 818 FROM_HERE, | 903 FROM_HERE, base::Bind(&VerifyRunsTasksOnCurrentThread, GetParam(), |
| 819 base::Bind(&VerifyRunsTasksOnCurrentThread, unsequenced_task_runner, | 904 unsequenced_task_runner, sequenced_task_runner_1, |
| 820 sequenced_task_runner_1, base::RetainedRef(pool()), | 905 base::RetainedRef(pool()), |
| 821 base::RetainedRef(unused_pool_owner.pool()))); | 906 base::RetainedRef(unused_pool_owner.pool()))); |
| 822 } | 907 } |
| 823 | 908 |
| 824 // Checks that tasks are destroyed in the right context during shutdown. If a | 909 // Checks that tasks are destroyed in the right context during shutdown. If a |
| 825 // task is destroyed while SequencedWorkerPool's global lock is held, | 910 // task is destroyed while SequencedWorkerPool's global lock is held, |
| 826 // SequencedWorkerPool might deadlock. | 911 // SequencedWorkerPool might deadlock. |
| 827 TEST_F(SequencedWorkerPoolTest, AvoidsDeadlockOnShutdown) { | 912 TEST_P(SequencedWorkerPoolTest, AvoidsDeadlockOnShutdown) { |
| 913 // Note: The TaskScheduler does not destroy tasks on shutdown. | |
|
gab
2016/09/16 20:16:10
Why does it pass in redirection then?! Are the Des
fdoray
2016/09/16 21:21:31
DestructionDeadlockChecker verifies that using the
| |
| 914 | |
| 828 for (int i = 0; i < 4; ++i) { | 915 for (int i = 0; i < 4; ++i) { |
| 829 scoped_refptr<DestructionDeadlockChecker> checker( | 916 scoped_refptr<DestructionDeadlockChecker> checker( |
| 830 new DestructionDeadlockChecker(pool())); | 917 new DestructionDeadlockChecker(pool())); |
| 831 tracker()->PostRepostingTask(pool(), checker); | 918 tracker()->PostRepostingTask(pool(), checker); |
| 832 } | 919 } |
| 833 | 920 |
| 834 // Shutting down the pool should destroy the DestructionDeadlockCheckers, | 921 // Shutting down the pool should destroy the DestructionDeadlockCheckers, |
| 835 // which in turn should not deadlock in their destructors. | 922 // which in turn should not deadlock in their destructors. |
| 836 pool()->Shutdown(); | 923 pool()->Shutdown(); |
| 837 } | 924 } |
| 838 | 925 |
| 839 // Similar to the test AvoidsDeadlockOnShutdown, but there are now also | 926 // Similar to the test AvoidsDeadlockOnShutdown, but there are now also |
| 840 // sequenced, blocking tasks in the queue during shutdown. | 927 // sequenced, blocking tasks in the queue during shutdown. |
| 841 TEST_F(SequencedWorkerPoolTest, | 928 TEST_P(SequencedWorkerPoolTest, |
| 842 AvoidsDeadlockOnShutdownWithSequencedBlockingTasks) { | 929 AvoidsDeadlockOnShutdownWithSequencedBlockingTasks) { |
| 930 // This test can't run when tasks are redirected to TaskScheduler because it | |
| 931 // doesn't provide a way to limit the number of BLOCK_SHUTDOWN tasks posted | |
| 932 // during shutdown. | |
|
gab
2016/09/16 20:16:10
I don't understand what this test has to do with t
fdoray
2016/09/16 21:21:31
Clarified the comment.
| |
| 933 if (GetParam() == SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER) | |
| 934 return; | |
| 935 | |
| 843 const std::string sequence_token_name("name"); | 936 const std::string sequence_token_name("name"); |
| 844 for (int i = 0; i < 4; ++i) { | 937 for (int i = 0; i < 4; ++i) { |
| 845 scoped_refptr<DestructionDeadlockChecker> checker( | 938 scoped_refptr<DestructionDeadlockChecker> checker( |
| 846 new DestructionDeadlockChecker(pool())); | 939 new DestructionDeadlockChecker(pool())); |
| 847 tracker()->PostRepostingTask(pool(), checker); | 940 tracker()->PostRepostingTask(pool(), checker); |
| 848 | 941 |
| 849 SequencedWorkerPool::SequenceToken token1 = | 942 SequencedWorkerPool::SequenceToken token1 = |
| 850 pool()->GetNamedSequenceToken(sequence_token_name); | 943 pool()->GetNamedSequenceToken(sequence_token_name); |
| 851 tracker()->PostRepostingBlockingTask(pool(), token1); | 944 tracker()->PostRepostingBlockingTask(pool(), token1); |
| 852 } | 945 } |
| 853 | 946 |
| 854 // Shutting down the pool should destroy the DestructionDeadlockCheckers, | 947 // Shutting down the pool should destroy the DestructionDeadlockCheckers, |
| 855 // which in turn should not deadlock in their destructors. | 948 // which in turn should not deadlock in their destructors. |
| 856 pool()->Shutdown(); | 949 pool()->Shutdown(); |
| 857 } | 950 } |
| 858 | 951 |
| 859 // Verify that FlushForTesting works as intended. | 952 // Verify that FlushForTesting works as intended. |
| 860 TEST_F(SequencedWorkerPoolTest, FlushForTesting) { | 953 TEST_P(SequencedWorkerPoolTest, FlushForTesting) { |
| 954 // FlushForTesting() can't be called when tasks are redirected to the | |
| 955 // TaskScheduler. | |
| 956 if (GetParam() == SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER) | |
| 957 return; | |
| 958 | |
| 861 // Should be fine to call on a new instance. | 959 // Should be fine to call on a new instance. |
| 862 pool()->FlushForTesting(); | 960 pool()->FlushForTesting(); |
| 863 | 961 |
| 864 // Queue up a bunch of work, including a long delayed task and | 962 // Queue up a bunch of work, including a long delayed task and |
| 865 // a task that produces additional tasks as an artifact. | 963 // a task that produces additional tasks as an artifact. |
| 866 pool()->PostDelayedWorkerTask( | 964 pool()->PostDelayedWorkerTask( |
| 867 FROM_HERE, | 965 FROM_HERE, |
| 868 base::Bind(&TestTracker::FastTask, tracker(), 0), | 966 base::Bind(&TestTracker::FastTask, tracker(), 0), |
| 869 TimeDelta::FromMinutes(5)); | 967 TimeDelta::FromMinutes(5)); |
| 870 pool()->PostWorkerTask(FROM_HERE, | 968 pool()->PostWorkerTask(FROM_HERE, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 905 SequencedWorkerPool::GetSequenceTokenForCurrentThread(); | 1003 SequencedWorkerPool::GetSequenceTokenForCurrentThread(); |
| 906 EXPECT_EQ(expected_token.ToString(), token.ToString()); | 1004 EXPECT_EQ(expected_token.ToString(), token.ToString()); |
| 907 | 1005 |
| 908 scoped_refptr<SequencedWorkerPool> pool = | 1006 scoped_refptr<SequencedWorkerPool> pool = |
| 909 SequencedWorkerPool::GetWorkerPoolForCurrentThread(); | 1007 SequencedWorkerPool::GetWorkerPoolForCurrentThread(); |
| 910 EXPECT_EQ(expected_pool, pool); | 1008 EXPECT_EQ(expected_pool, pool); |
| 911 } | 1009 } |
| 912 | 1010 |
| 913 } // namespace | 1011 } // namespace |
| 914 | 1012 |
| 915 TEST_F(SequencedWorkerPoolTest, GetWorkerPoolAndSequenceTokenForCurrentThread) { | 1013 TEST_P(SequencedWorkerPoolTest, GetWorkerPoolAndSequenceTokenForCurrentThread) { |
| 1014 // GetSequenceTokenForCurrentThread() and GetWorkerPoolForCurrentThread() | |
| 1015 // respectively return an invalid token and nullptr from a task posted to a | |
| 1016 // SequencedWorkerPool when redirection to TaskScheduler is enabled. These | |
| 1017 // methods are only used from SequencedTaskRunnerHandle and | |
| 1018 // SequenceCheckerImpl which work fine in TaskScheduler. | |
| 1019 if (GetParam() == SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER) | |
| 1020 return; | |
| 1021 | |
| 916 EnsureAllWorkersCreated(); | 1022 EnsureAllWorkersCreated(); |
| 917 | 1023 |
| 918 // The current thread should have neither a worker pool nor a sequence token. | 1024 // The current thread should have neither a worker pool nor a sequence token. |
| 919 SequencedWorkerPool::SequenceToken local_token = | 1025 SequencedWorkerPool::SequenceToken local_token = |
| 920 SequencedWorkerPool::GetSequenceTokenForCurrentThread(); | 1026 SequencedWorkerPool::GetSequenceTokenForCurrentThread(); |
| 921 scoped_refptr<SequencedWorkerPool> local_pool = | 1027 scoped_refptr<SequencedWorkerPool> local_pool = |
| 922 SequencedWorkerPool::GetWorkerPoolForCurrentThread(); | 1028 SequencedWorkerPool::GetWorkerPoolForCurrentThread(); |
| 923 EXPECT_FALSE(local_token.IsValid()) << local_token.ToString(); | 1029 EXPECT_FALSE(local_token.IsValid()) << local_token.ToString(); |
| 924 EXPECT_FALSE(local_pool); | 1030 EXPECT_FALSE(local_pool); |
| 925 | 1031 |
| 926 SequencedWorkerPool::SequenceToken token1 = pool()->GetSequenceToken(); | 1032 SequencedWorkerPool::SequenceToken token1 = pool()->GetSequenceToken(); |
| 927 SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken(); | 1033 SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken(); |
| 928 pool()->PostSequencedWorkerTask( | 1034 pool()->PostSequencedWorkerTask( |
| 929 token1, FROM_HERE, | 1035 token1, FROM_HERE, |
| 930 base::Bind(&CheckWorkerPoolAndSequenceToken, pool(), token1)); | 1036 base::Bind(&CheckWorkerPoolAndSequenceToken, pool(), token1)); |
| 931 pool()->PostSequencedWorkerTask( | 1037 pool()->PostSequencedWorkerTask( |
| 932 token2, FROM_HERE, | 1038 token2, FROM_HERE, |
| 933 base::Bind(&CheckWorkerPoolAndSequenceToken, pool(), token2)); | 1039 base::Bind(&CheckWorkerPoolAndSequenceToken, pool(), token2)); |
| 934 | 1040 |
| 935 pool()->PostWorkerTask(FROM_HERE, | 1041 pool()->PostWorkerTask(FROM_HERE, |
| 936 base::Bind(&CheckWorkerPoolAndSequenceToken, pool(), | 1042 base::Bind(&CheckWorkerPoolAndSequenceToken, pool(), |
| 937 SequencedWorkerPool::SequenceToken())); | 1043 SequencedWorkerPool::SequenceToken())); |
| 938 | 1044 |
| 939 pool()->FlushForTesting(); | 1045 pool()->FlushForTesting(); |
| 940 } | 1046 } |
| 941 | 1047 |
| 942 TEST_F(SequencedWorkerPoolTest, ShutsDownCleanWithContinueOnShutdown) { | 1048 TEST_P(SequencedWorkerPoolTest, ShutsDownCleanWithContinueOnShutdown) { |
| 943 scoped_refptr<SequencedTaskRunner> task_runner = | 1049 scoped_refptr<SequencedTaskRunner> task_runner = |
| 944 pool()->GetSequencedTaskRunnerWithShutdownBehavior( | 1050 pool()->GetSequencedTaskRunnerWithShutdownBehavior( |
| 945 pool()->GetSequenceToken(), | 1051 pool()->GetSequenceToken(), |
| 946 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); | 1052 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); |
| 947 | 1053 |
| 948 // Upon test exit, should shut down without hanging. | 1054 // Upon test exit, should shut down without hanging. |
| 949 pool()->Shutdown(); | 1055 pool()->Shutdown(); |
| 950 } | 1056 } |
| 951 | 1057 |
| 1058 INSTANTIATE_TEST_CASE_P( | |
| 1059 NoRedirection, | |
| 1060 SequencedWorkerPoolTest, | |
| 1061 ::testing::Values(SequencedWorkerPoolRedirection::NONE)); | |
| 1062 INSTANTIATE_TEST_CASE_P( | |
| 1063 RedirectionToTaskScheduler, | |
| 1064 SequencedWorkerPoolTest, | |
| 1065 ::testing::Values(SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER)); | |
| 1066 | |
| 952 class SequencedWorkerPoolTaskRunnerTestDelegate { | 1067 class SequencedWorkerPoolTaskRunnerTestDelegate { |
| 953 public: | 1068 public: |
| 954 SequencedWorkerPoolTaskRunnerTestDelegate() {} | 1069 SequencedWorkerPoolTaskRunnerTestDelegate() {} |
| 955 | 1070 |
| 956 ~SequencedWorkerPoolTaskRunnerTestDelegate() {} | 1071 ~SequencedWorkerPoolTaskRunnerTestDelegate() {} |
| 957 | 1072 |
| 958 void StartTaskRunner() { | 1073 void StartTaskRunner() { |
| 959 pool_owner_.reset( | 1074 pool_owner_.reset( |
| 960 new SequencedWorkerPoolOwner(10, "SequencedWorkerPoolTaskRunnerTest")); | 1075 new SequencedWorkerPoolOwner(10, "SequencedWorkerPoolTaskRunnerTest")); |
| 961 } | 1076 } |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1068 SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, | 1183 SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, |
| 1069 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); | 1184 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); |
| 1070 INSTANTIATE_TYPED_TEST_CASE_P( | 1185 INSTANTIATE_TYPED_TEST_CASE_P( |
| 1071 SequencedWorkerPoolSequencedTaskRunner, | 1186 SequencedWorkerPoolSequencedTaskRunner, |
| 1072 SequencedTaskRunnerDelayedTest, | 1187 SequencedTaskRunnerDelayedTest, |
| 1073 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); | 1188 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); |
| 1074 | 1189 |
| 1075 } // namespace | 1190 } // namespace |
| 1076 | 1191 |
| 1077 } // namespace base | 1192 } // namespace base |
| OLD | NEW |