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