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

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: Review feedback 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());
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
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
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
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
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
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