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