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 <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 291 const size_t kNumTasks = 20; | 291 const size_t kNumTasks = 20; |
| 292 for (size_t i = 1; i < kNumTasks; i++) { | 292 for (size_t i = 1; i < kNumTasks; i++) { |
| 293 base::Closure fast_task = | 293 base::Closure fast_task = |
| 294 base::Bind(&TestTracker::FastTask, tracker(), i); | 294 base::Bind(&TestTracker::FastTask, tracker(), i); |
| 295 pool1.pool()->PostWorkerTask(FROM_HERE, fast_task); | 295 pool1.pool()->PostWorkerTask(FROM_HERE, fast_task); |
| 296 pool2.pool()->PostWorkerTask(FROM_HERE, fast_task); | 296 pool2.pool()->PostWorkerTask(FROM_HERE, fast_task); |
| 297 } | 297 } |
| 298 | 298 |
| 299 std::vector<int> result = | 299 std::vector<int> result = |
| 300 tracker()->WaitUntilTasksComplete(2*kNumTasks); | 300 tracker()->WaitUntilTasksComplete(2*kNumTasks); |
| 301 EXPECT_EQ(2*kNumTasks, result.size()); | 301 EXPECT_EQ(2*kNumTasks, result.size()); |
|
jar (doing other things)
2012/07/20 02:21:17
nit: (though again, not yours) spaces around *
| |
| 302 | 302 |
| 303 pool2.pool()->Shutdown(); | 303 pool2.pool()->Shutdown(); |
| 304 pool1.pool()->Shutdown(); | 304 pool1.pool()->Shutdown(); |
| 305 } | 305 } |
| 306 | 306 |
| 307 // Test that tasks with the same sequence token are executed in order but don't | 307 // Test that tasks with the same sequence token are executed in order but don't |
| 308 // affect other tasks. | 308 // affect other tasks. |
| 309 TEST_F(SequencedWorkerPoolTest, Sequence) { | 309 TEST_F(SequencedWorkerPoolTest, Sequence) { |
| 310 // Fill all the worker threads except one. | 310 // Fill all the worker threads except one. |
| 311 const size_t kNumBackgroundTasks = kNumWorkerThreads - 1; | 311 const size_t kNumBackgroundTasks = kNumWorkerThreads - 1; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 339 base::Bind(&TestTracker::FastTask, tracker(), 200)); | 339 base::Bind(&TestTracker::FastTask, tracker(), 200)); |
| 340 pool()->PostSequencedWorkerTask( | 340 pool()->PostSequencedWorkerTask( |
| 341 token2, FROM_HERE, | 341 token2, FROM_HERE, |
| 342 base::Bind(&TestTracker::FastTask, tracker(), 201)); | 342 base::Bind(&TestTracker::FastTask, tracker(), 201)); |
| 343 EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size()); | 343 EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size()); |
| 344 | 344 |
| 345 // Let one background task complete. This should then let both tasks of | 345 // Let one background task complete. This should then let both tasks of |
| 346 // token2 run to completion in order. The second task of token1 should still | 346 // token2 run to completion in order. The second task of token1 should still |
| 347 // be blocked. | 347 // be blocked. |
| 348 background_blocker.Unblock(1); | 348 background_blocker.Unblock(1); |
| 349 std::vector<int> result = tracker()->WaitUntilTasksComplete(3); | 349 std::vector<int> result = tracker()->WaitUntilTasksComplete(3); |
|
jar (doing other things)
2012/07/20 02:21:17
kNumWorkerThreads
Ryan Sleevi
2012/07/20 02:53:59
This is correct as-is. "3" refers to the one paren
| |
| 350 ASSERT_EQ(3u, result.size()); | 350 ASSERT_EQ(3u, result.size()); |
| 351 EXPECT_EQ(200, result[1]); | 351 EXPECT_EQ(200, result[1]); |
| 352 EXPECT_EQ(201, result[2]); | 352 EXPECT_EQ(201, result[2]); |
| 353 | 353 |
| 354 // Finish the rest of the background tasks. This should leave some workers | 354 // Finish the rest of the background tasks. This should leave some workers |
| 355 // free with the second token1 task still blocked on the first. | 355 // free with the second token1 task still blocked on the first. |
| 356 background_blocker.Unblock(kNumBackgroundTasks - 1); | 356 background_blocker.Unblock(kNumBackgroundTasks - 1); |
| 357 EXPECT_EQ(kNumBackgroundTasks + 2, | 357 EXPECT_EQ(kNumBackgroundTasks + 2, |
| 358 tracker()->WaitUntilTasksComplete(kNumBackgroundTasks + 2).size()); | 358 tracker()->WaitUntilTasksComplete(kNumBackgroundTasks + 2).size()); |
| 359 | 359 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 392 base::Bind(&TestTracker::FastTask, tracker(), 102), | 392 base::Bind(&TestTracker::FastTask, tracker(), 102), |
| 393 SequencedWorkerPool::BLOCK_SHUTDOWN); | 393 SequencedWorkerPool::BLOCK_SHUTDOWN); |
| 394 | 394 |
| 395 // Shutdown the worker pool. This should discard all non-blocking tasks. | 395 // Shutdown the worker pool. This should discard all non-blocking tasks. |
| 396 SetWillWaitForShutdownCallback( | 396 SetWillWaitForShutdownCallback( |
| 397 base::Bind(&EnsureTasksToCompleteCountAndUnblock, | 397 base::Bind(&EnsureTasksToCompleteCountAndUnblock, |
| 398 scoped_refptr<TestTracker>(tracker()), 0, | 398 scoped_refptr<TestTracker>(tracker()), 0, |
| 399 &blocker, kNumWorkerThreads)); | 399 &blocker, kNumWorkerThreads)); |
| 400 pool()->Shutdown(); | 400 pool()->Shutdown(); |
| 401 | 401 |
| 402 std::vector<int> result = tracker()->WaitUntilTasksComplete(4); | 402 std::vector<int> result = |
| 403 tracker()->WaitUntilTasksComplete(kNumWorkerThreads + 1); | |
| 403 | 404 |
| 404 // The kNumWorkerThread items should have completed, plus the BLOCK_SHUTDOWN | 405 // The kNumWorkerThread items should have completed, plus the BLOCK_SHUTDOWN |
| 405 // one, in no particular order. | 406 // one, in no particular order. |
| 406 ASSERT_EQ(4u, result.size()); | 407 ASSERT_EQ(kNumWorkerThreads + 1, result.size()); |
| 407 for (size_t i = 0; i < kNumWorkerThreads; i++) { | 408 for (size_t i = 0; i < kNumWorkerThreads; i++) { |
| 408 EXPECT_TRUE(std::find(result.begin(), result.end(), static_cast<int>(i)) != | 409 EXPECT_TRUE(std::find(result.begin(), result.end(), static_cast<int>(i)) != |
| 409 result.end()); | 410 result.end()); |
| 410 } | 411 } |
| 411 EXPECT_TRUE(std::find(result.begin(), result.end(), 102) != result.end()); | 412 EXPECT_TRUE(std::find(result.begin(), result.end(), 102) != result.end()); |
| 412 } | 413 } |
| 413 | 414 |
| 414 // Tests that CONTINUE_ON_SHUTDOWN tasks don't block shutdown. | 415 // Tests that CONTINUE_ON_SHUTDOWN tasks don't block shutdown. |
| 415 TEST_F(SequencedWorkerPoolTest, ContinueOnShutdown) { | 416 TEST_F(SequencedWorkerPoolTest, ContinueOnShutdown) { |
| 416 scoped_refptr<TaskRunner> runner(pool()->GetTaskRunnerWithShutdownBehavior( | 417 scoped_refptr<TaskRunner> runner(pool()->GetTaskRunnerWithShutdownBehavior( |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 428 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); | 429 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); |
| 429 runner->PostTask( | 430 runner->PostTask( |
| 430 FROM_HERE, | 431 FROM_HERE, |
| 431 base::Bind(&TestTracker::BlockTask, | 432 base::Bind(&TestTracker::BlockTask, |
| 432 tracker(), 1, &blocker)); | 433 tracker(), 1, &blocker)); |
| 433 sequenced_runner->PostTask( | 434 sequenced_runner->PostTask( |
| 434 FROM_HERE, | 435 FROM_HERE, |
| 435 base::Bind(&TestTracker::BlockTask, | 436 base::Bind(&TestTracker::BlockTask, |
| 436 tracker(), 2, &blocker)); | 437 tracker(), 2, &blocker)); |
| 437 | 438 |
| 438 tracker()->WaitUntilTasksBlocked(3); | 439 tracker()->WaitUntilTasksBlocked(3); |
|
jar (doing other things)
2012/07/20 02:21:17
Should this be kNumWorkerThreads instead of 3?
Ryan Sleevi
2012/07/20 02:53:59
Unfortunately, no. It refers to the three tasks po
| |
| 439 | 440 |
| 440 // This should not block. If this test hangs, it means it failed. | 441 // This should not block. If this test hangs, it means it failed. |
| 441 pool()->Shutdown(); | 442 pool()->Shutdown(); |
| 442 | 443 |
| 443 // The task should not have completed yet. | 444 // The task should not have completed yet. |
| 444 EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size()); | 445 EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size()); |
| 445 | 446 |
| 446 // Posting more tasks should fail. | 447 // Posting more tasks should fail. |
| 447 EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( | 448 EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( |
| 448 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0), | 449 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0), |
| 449 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); | 450 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); |
| 450 EXPECT_FALSE(runner->PostTask( | 451 EXPECT_FALSE(runner->PostTask( |
| 451 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0))); | 452 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0))); |
| 452 EXPECT_FALSE(sequenced_runner->PostTask( | 453 EXPECT_FALSE(sequenced_runner->PostTask( |
| 453 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0))); | 454 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0))); |
| 454 | 455 |
| 455 // Continue the background thread and make sure the tasks can complete. | 456 // Continue the background thread and make sure the tasks can complete. |
| 456 blocker.Unblock(3); | 457 blocker.Unblock(3); |
| 457 std::vector<int> result = tracker()->WaitUntilTasksComplete(3); | 458 std::vector<int> result = tracker()->WaitUntilTasksComplete(3); |
|
jar (doing other things)
2012/07/20 02:21:17
nit: kNumWorkerThreads?
Ryan Sleevi
2012/07/20 02:53:59
Same 'magic' constant from above.
| |
| 458 EXPECT_EQ(3u, result.size()); | 459 EXPECT_EQ(3u, result.size()); |
| 459 } | 460 } |
| 460 | 461 |
| 462 // Tests that SKIP_ON_SHUTDOWN tasks that have been started block Shutdown | |
| 463 // until they stop, but tasks not yet started do not. | |
| 464 TEST_F(SequencedWorkerPoolTest, SkipOnShutdown) { | |
| 465 // Start tasks to take all the threads and block them. | |
| 466 EnsureAllWorkersCreated(); | |
| 467 ThreadBlocker blocker; | |
| 468 | |
| 469 // Now block all the threads with SKIP_ON_SHUTDOWN. Shutdown() should not | |
| 470 // return until these tasks have completed. | |
| 471 for (size_t i = 0; i < kNumWorkerThreads; i++) { | |
| 472 pool()->PostWorkerTaskWithShutdownBehavior( | |
| 473 FROM_HERE, | |
| 474 base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker), | |
| 475 SequencedWorkerPool::SKIP_ON_SHUTDOWN); | |
| 476 } | |
| 477 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); | |
| 478 | |
| 479 // Now post an additional task as SKIP_ON_SHUTDOWN, which should not be | |
| 480 // executed once Shutdown() has been called. | |
| 481 pool()->PostWorkerTaskWithShutdownBehavior( | |
| 482 FROM_HERE, | |
| 483 base::Bind(&TestTracker::BlockTask, | |
| 484 tracker(), 0, &blocker), | |
| 485 SequencedWorkerPool::SKIP_ON_SHUTDOWN); | |
| 486 | |
| 487 // This callback will only be invoked if SKIP_ON_SHUTDOWN tasks that have | |
| 488 // been started block shutdown. | |
| 489 SetWillWaitForShutdownCallback( | |
| 490 base::Bind(&EnsureTasksToCompleteCountAndUnblock, | |
| 491 scoped_refptr<TestTracker>(tracker()), 0, | |
| 492 &blocker, kNumWorkerThreads)); | |
| 493 | |
| 494 // No tasks should have completed yet. | |
| 495 EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size()); | |
| 496 | |
| 497 // This should not block. If this test hangs, it means it failed. | |
| 498 pool()->Shutdown(); | |
|
jar (doing other things)
2012/07/20 02:21:17
Do you think there is a another test where we post
Ryan Sleevi
2012/07/20 02:53:59
No, but I've added one.
| |
| 499 | |
| 500 // Shutdown should not return until all of the tasks have completed. | |
| 501 std::vector<int> result = | |
| 502 tracker()->WaitUntilTasksComplete(kNumWorkerThreads); | |
| 503 | |
| 504 // Only taks marked SKIP_ON_SHUTDOWN that were already started should be | |
|
jar (doing other things)
2012/07/20 02:21:17
nit: taks-->tasks
| |
| 505 // allowed to complete. No additional non-blocking tasks should have been | |
| 506 // started. | |
| 507 ASSERT_EQ(kNumWorkerThreads, result.size()); | |
| 508 for (size_t i = 0; i < kNumWorkerThreads; i++) { | |
| 509 EXPECT_TRUE(std::find(result.begin(), result.end(), static_cast<int>(i)) != | |
| 510 result.end()); | |
| 511 } | |
| 512 } | |
| 513 | |
| 461 // Ensure all worker threads are created, and then trigger a spurious | 514 // Ensure all worker threads are created, and then trigger a spurious |
| 462 // work signal. This shouldn't cause any other work signals to be | 515 // work signal. This shouldn't cause any other work signals to be |
| 463 // triggered. This is a regression test for http://crbug.com/117469. | 516 // triggered. This is a regression test for http://crbug.com/117469. |
| 464 TEST_F(SequencedWorkerPoolTest, SpuriousWorkSignal) { | 517 TEST_F(SequencedWorkerPoolTest, SpuriousWorkSignal) { |
| 465 EnsureAllWorkersCreated(); | 518 EnsureAllWorkersCreated(); |
| 466 int old_has_work_call_count = has_work_call_count(); | 519 int old_has_work_call_count = has_work_call_count(); |
| 467 pool()->SignalHasWorkForTesting(); | 520 pool()->SignalHasWorkForTesting(); |
| 468 // This is inherently racy, but can only produce false positives. | 521 // This is inherently racy, but can only produce false positives. |
| 469 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); | 522 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); |
| 470 EXPECT_EQ(old_has_work_call_count + 1, has_work_call_count()); | 523 EXPECT_EQ(old_has_work_call_count + 1, has_work_call_count()); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 640 SequencedWorkerPoolSequencedTaskRunner, TaskRunnerTest, | 693 SequencedWorkerPoolSequencedTaskRunner, TaskRunnerTest, |
| 641 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); | 694 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); |
| 642 | 695 |
| 643 INSTANTIATE_TYPED_TEST_CASE_P( | 696 INSTANTIATE_TYPED_TEST_CASE_P( |
| 644 SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, | 697 SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, |
| 645 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); | 698 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); |
| 646 | 699 |
| 647 } // namespace | 700 } // namespace |
| 648 | 701 |
| 649 } // namespace base | 702 } // namespace base |
| OLD | NEW |