Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: base/threading/sequenced_worker_pool_unittest.cc

Issue 10807045: Ensure SequencedWorkerPool::Shutdown() blocks for already-started SKIP_ON_SHUTDOWN tasks (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Test fix Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/threading/sequenced_worker_pool.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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());
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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 tracker()->WaitUntilTasksComplete(kNumBackgroundTasks + 2).size()); 358 tracker()->WaitUntilTasksComplete(kNumBackgroundTasks + 2).size());
359 359
360 // Allow the first task of token1 to complete. This should run the second. 360 // Allow the first task of token1 to complete. This should run the second.
361 blocker.Unblock(1); 361 blocker.Unblock(1);
362 result = tracker()->WaitUntilTasksComplete(kNumBackgroundTasks + 4); 362 result = tracker()->WaitUntilTasksComplete(kNumBackgroundTasks + 4);
363 ASSERT_EQ(kNumBackgroundTasks + 4, result.size()); 363 ASSERT_EQ(kNumBackgroundTasks + 4, result.size());
364 EXPECT_EQ(100, result[result.size() - 2]); 364 EXPECT_EQ(100, result[result.size() - 2]);
365 EXPECT_EQ(101, result[result.size() - 1]); 365 EXPECT_EQ(101, result[result.size() - 1]);
366 } 366 }
367 367
368 // Tests that any tasks posted after Shutdown are ignored.
369 TEST_F(SequencedWorkerPoolTest, IgnoresAfterShutdown) {
370 // Start tasks to take all the threads and block them.
371 EnsureAllWorkersCreated();
372 ThreadBlocker blocker;
373 for (size_t i = 0; i < kNumWorkerThreads; i++) {
374 pool()->PostWorkerTask(FROM_HERE,
375 base::Bind(&TestTracker::BlockTask,
376 tracker(), i, &blocker));
377 }
378 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads);
379
380 // Shutdown the worker pool. This should discard all non-blocking tasks.
381 SetWillWaitForShutdownCallback(
382 base::Bind(&EnsureTasksToCompleteCountAndUnblock,
383 scoped_refptr<TestTracker>(tracker()), 0,
384 &blocker, kNumWorkerThreads));
385 pool()->Shutdown();
386
387 int old_has_work_call_count = has_work_call_count();
388
389 std::vector<int> result =
390 tracker()->WaitUntilTasksComplete(kNumWorkerThreads);
391
392 // The kNumWorkerThread items should have completed, in no particular
393 // order.
394 ASSERT_EQ(kNumWorkerThreads, result.size());
395 for (size_t i = 0; i < kNumWorkerThreads; i++) {
396 EXPECT_TRUE(std::find(result.begin(), result.end(), static_cast<int>(i)) !=
397 result.end());
398 }
399
400 // No further tasks, regardless of shutdown mode, should be allowed.
401 EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior(
402 FROM_HERE,
403 base::Bind(&TestTracker::FastTask, tracker(), 100),
404 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN));
405 EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior(
406 FROM_HERE,
407 base::Bind(&TestTracker::FastTask, tracker(), 101),
408 SequencedWorkerPool::SKIP_ON_SHUTDOWN));
409 EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior(
410 FROM_HERE,
411 base::Bind(&TestTracker::FastTask, tracker(), 102),
412 SequencedWorkerPool::BLOCK_SHUTDOWN));
413
414 ASSERT_EQ(old_has_work_call_count, has_work_call_count());
415 }
416
368 // Tests that unrun tasks are discarded properly according to their shutdown 417 // Tests that unrun tasks are discarded properly according to their shutdown
369 // mode. 418 // mode.
370 TEST_F(SequencedWorkerPoolTest, DiscardOnShutdown) { 419 TEST_F(SequencedWorkerPoolTest, DiscardOnShutdown) {
371 // Start tasks to take all the threads and block them. 420 // Start tasks to take all the threads and block them.
372 EnsureAllWorkersCreated(); 421 EnsureAllWorkersCreated();
373 ThreadBlocker blocker; 422 ThreadBlocker blocker;
374 for (size_t i = 0; i < kNumWorkerThreads; i++) { 423 for (size_t i = 0; i < kNumWorkerThreads; i++) {
375 pool()->PostWorkerTask(FROM_HERE, 424 pool()->PostWorkerTask(FROM_HERE,
376 base::Bind(&TestTracker::BlockTask, 425 base::Bind(&TestTracker::BlockTask,
377 tracker(), i, &blocker)); 426 tracker(), i, &blocker));
(...skipping 14 matching lines...) Expand all
392 base::Bind(&TestTracker::FastTask, tracker(), 102), 441 base::Bind(&TestTracker::FastTask, tracker(), 102),
393 SequencedWorkerPool::BLOCK_SHUTDOWN); 442 SequencedWorkerPool::BLOCK_SHUTDOWN);
394 443
395 // Shutdown the worker pool. This should discard all non-blocking tasks. 444 // Shutdown the worker pool. This should discard all non-blocking tasks.
396 SetWillWaitForShutdownCallback( 445 SetWillWaitForShutdownCallback(
397 base::Bind(&EnsureTasksToCompleteCountAndUnblock, 446 base::Bind(&EnsureTasksToCompleteCountAndUnblock,
398 scoped_refptr<TestTracker>(tracker()), 0, 447 scoped_refptr<TestTracker>(tracker()), 0,
399 &blocker, kNumWorkerThreads)); 448 &blocker, kNumWorkerThreads));
400 pool()->Shutdown(); 449 pool()->Shutdown();
401 450
402 std::vector<int> result = tracker()->WaitUntilTasksComplete(4); 451 std::vector<int> result =
452 tracker()->WaitUntilTasksComplete(kNumWorkerThreads + 1);
403 453
404 // The kNumWorkerThread items should have completed, plus the BLOCK_SHUTDOWN 454 // The kNumWorkerThread items should have completed, plus the BLOCK_SHUTDOWN
405 // one, in no particular order. 455 // one, in no particular order.
406 ASSERT_EQ(4u, result.size()); 456 ASSERT_EQ(kNumWorkerThreads + 1, result.size());
407 for (size_t i = 0; i < kNumWorkerThreads; i++) { 457 for (size_t i = 0; i < kNumWorkerThreads; i++) {
408 EXPECT_TRUE(std::find(result.begin(), result.end(), static_cast<int>(i)) != 458 EXPECT_TRUE(std::find(result.begin(), result.end(), static_cast<int>(i)) !=
409 result.end()); 459 result.end());
410 } 460 }
411 EXPECT_TRUE(std::find(result.begin(), result.end(), 102) != result.end()); 461 EXPECT_TRUE(std::find(result.begin(), result.end(), 102) != result.end());
412 } 462 }
413 463
414 // Tests that CONTINUE_ON_SHUTDOWN tasks don't block shutdown. 464 // Tests that CONTINUE_ON_SHUTDOWN tasks don't block shutdown.
415 TEST_F(SequencedWorkerPoolTest, ContinueOnShutdown) { 465 TEST_F(SequencedWorkerPoolTest, ContinueOnShutdown) {
416 scoped_refptr<TaskRunner> runner(pool()->GetTaskRunnerWithShutdownBehavior( 466 scoped_refptr<TaskRunner> runner(pool()->GetTaskRunnerWithShutdownBehavior(
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0))); 501 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0)));
452 EXPECT_FALSE(sequenced_runner->PostTask( 502 EXPECT_FALSE(sequenced_runner->PostTask(
453 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0))); 503 FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0)));
454 504
455 // Continue the background thread and make sure the tasks can complete. 505 // Continue the background thread and make sure the tasks can complete.
456 blocker.Unblock(3); 506 blocker.Unblock(3);
457 std::vector<int> result = tracker()->WaitUntilTasksComplete(3); 507 std::vector<int> result = tracker()->WaitUntilTasksComplete(3);
458 EXPECT_EQ(3u, result.size()); 508 EXPECT_EQ(3u, result.size());
459 } 509 }
460 510
511 // Tests that SKIP_ON_SHUTDOWN tasks that have been started block Shutdown
512 // until they stop, but tasks not yet started do not.
513 TEST_F(SequencedWorkerPoolTest, SkipOnShutdown) {
514 // Start tasks to take all the threads and block them.
515 EnsureAllWorkersCreated();
516 ThreadBlocker blocker;
517
518 // Now block all the threads with SKIP_ON_SHUTDOWN. Shutdown() should not
519 // return until these tasks have completed.
520 for (size_t i = 0; i < kNumWorkerThreads; i++) {
521 pool()->PostWorkerTaskWithShutdownBehavior(
522 FROM_HERE,
523 base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker),
524 SequencedWorkerPool::SKIP_ON_SHUTDOWN);
525 }
526 tracker()->WaitUntilTasksBlocked(kNumWorkerThreads);
527
528 // Now post an additional task as SKIP_ON_SHUTDOWN, which should not be
529 // executed once Shutdown() has been called.
530 pool()->PostWorkerTaskWithShutdownBehavior(
531 FROM_HERE,
532 base::Bind(&TestTracker::BlockTask,
533 tracker(), 0, &blocker),
534 SequencedWorkerPool::SKIP_ON_SHUTDOWN);
535
536 // This callback will only be invoked if SKIP_ON_SHUTDOWN tasks that have
537 // been started block shutdown.
538 SetWillWaitForShutdownCallback(
539 base::Bind(&EnsureTasksToCompleteCountAndUnblock,
540 scoped_refptr<TestTracker>(tracker()), 0,
541 &blocker, kNumWorkerThreads));
542
543 // No tasks should have completed yet.
544 EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size());
545
546 // This should not block. If this test hangs, it means it failed.
547 pool()->Shutdown();
548
549 // Shutdown should not return until all of the tasks have completed.
550 std::vector<int> result =
551 tracker()->WaitUntilTasksComplete(kNumWorkerThreads);
552
553 // Only tasks marked SKIP_ON_SHUTDOWN that were already started should be
554 // allowed to complete. No additional non-blocking tasks should have been
555 // started.
556 ASSERT_EQ(kNumWorkerThreads, result.size());
557 for (size_t i = 0; i < kNumWorkerThreads; i++) {
558 EXPECT_TRUE(std::find(result.begin(), result.end(), static_cast<int>(i)) !=
559 result.end());
560 }
561 }
562
461 // Ensure all worker threads are created, and then trigger a spurious 563 // Ensure all worker threads are created, and then trigger a spurious
462 // work signal. This shouldn't cause any other work signals to be 564 // work signal. This shouldn't cause any other work signals to be
463 // triggered. This is a regression test for http://crbug.com/117469. 565 // triggered. This is a regression test for http://crbug.com/117469.
464 TEST_F(SequencedWorkerPoolTest, SpuriousWorkSignal) { 566 TEST_F(SequencedWorkerPoolTest, SpuriousWorkSignal) {
465 EnsureAllWorkersCreated(); 567 EnsureAllWorkersCreated();
466 int old_has_work_call_count = has_work_call_count(); 568 int old_has_work_call_count = has_work_call_count();
467 pool()->SignalHasWorkForTesting(); 569 pool()->SignalHasWorkForTesting();
468 // This is inherently racy, but can only produce false positives. 570 // This is inherently racy, but can only produce false positives.
469 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); 571 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
470 EXPECT_EQ(old_has_work_call_count + 1, has_work_call_count()); 572 EXPECT_EQ(old_has_work_call_count + 1, has_work_call_count());
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 SequencedWorkerPoolSequencedTaskRunner, TaskRunnerTest, 742 SequencedWorkerPoolSequencedTaskRunner, TaskRunnerTest,
641 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); 743 SequencedWorkerPoolSequencedTaskRunnerTestDelegate);
642 744
643 INSTANTIATE_TYPED_TEST_CASE_P( 745 INSTANTIATE_TYPED_TEST_CASE_P(
644 SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, 746 SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest,
645 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); 747 SequencedWorkerPoolSequencedTaskRunnerTestDelegate);
646 748
647 } // namespace 749 } // namespace
648 750
649 } // namespace base 751 } // namespace base
OLDNEW
« no previous file with comments | « base/threading/sequenced_worker_pool.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698