OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/task_scheduler/scheduler_worker.h" | 5 #include "base/task_scheduler/scheduler_worker.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
14 #include "base/macros.h" | 14 #include "base/macros.h" |
15 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
16 #include "base/memory/ref_counted.h" | |
16 #include "base/synchronization/condition_variable.h" | 17 #include "base/synchronization/condition_variable.h" |
17 #include "base/synchronization/waitable_event.h" | 18 #include "base/synchronization/waitable_event.h" |
18 #include "base/task_scheduler/scheduler_lock.h" | 19 #include "base/task_scheduler/scheduler_lock.h" |
19 #include "base/task_scheduler/sequence.h" | 20 #include "base/task_scheduler/sequence.h" |
20 #include "base/task_scheduler/task.h" | 21 #include "base/task_scheduler/task.h" |
21 #include "base/task_scheduler/task_tracker.h" | 22 #include "base/task_scheduler/task_tracker.h" |
23 #include "base/test/test_timeouts.h" | |
22 #include "base/threading/platform_thread.h" | 24 #include "base/threading/platform_thread.h" |
25 #include "base/threading/simple_thread.h" | |
23 #include "base/time/time.h" | 26 #include "base/time/time.h" |
24 #include "build/build_config.h" | 27 #include "build/build_config.h" |
25 #include "testing/gmock/include/gmock/gmock.h" | 28 #include "testing/gmock/include/gmock/gmock.h" |
26 #include "testing/gtest/include/gtest/gtest.h" | 29 #include "testing/gtest/include/gtest/gtest.h" |
27 | 30 |
28 #if defined(OS_WIN) | 31 #if defined(OS_WIN) |
29 #include <objbase.h> | 32 #include <objbase.h> |
30 #endif | 33 #endif |
31 | 34 |
32 using testing::_; | 35 using testing::_; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
114 std::vector<scoped_refptr<Sequence>> CreatedSequences() { | 117 std::vector<scoped_refptr<Sequence>> CreatedSequences() { |
115 AutoSchedulerLock auto_lock(lock_); | 118 AutoSchedulerLock auto_lock(lock_); |
116 return created_sequences_; | 119 return created_sequences_; |
117 } | 120 } |
118 | 121 |
119 std::vector<scoped_refptr<Sequence>> EnqueuedSequences() { | 122 std::vector<scoped_refptr<Sequence>> EnqueuedSequences() { |
120 AutoSchedulerLock auto_lock(lock_); | 123 AutoSchedulerLock auto_lock(lock_); |
121 return re_enqueued_sequences_; | 124 return re_enqueued_sequences_; |
122 } | 125 } |
123 | 126 |
124 std::unique_ptr<SchedulerWorker> worker_; | 127 scoped_refptr<SchedulerWorker> worker_; |
125 | 128 |
126 private: | 129 private: |
127 class TestSchedulerWorkerDelegate : public SchedulerWorkerDefaultDelegate { | 130 class TestSchedulerWorkerDelegate : public SchedulerWorkerDefaultDelegate { |
128 public: | 131 public: |
129 TestSchedulerWorkerDelegate(TaskSchedulerWorkerTest* outer) | 132 TestSchedulerWorkerDelegate(TaskSchedulerWorkerTest* outer) |
130 : outer_(outer) {} | 133 : outer_(outer) {} |
131 | 134 |
132 ~TestSchedulerWorkerDelegate() override { | 135 ~TestSchedulerWorkerDelegate() override { |
133 EXPECT_FALSE(IsCallToDidRunTaskExpected()); | 136 EXPECT_FALSE(IsCallToDidRunTaskExpected()); |
134 } | 137 } |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
348 TaskSchedulerWorkerTest, | 351 TaskSchedulerWorkerTest, |
349 ::testing::Values(1)); | 352 ::testing::Values(1)); |
350 INSTANTIATE_TEST_CASE_P(TwoTasksPerSequence, | 353 INSTANTIATE_TEST_CASE_P(TwoTasksPerSequence, |
351 TaskSchedulerWorkerTest, | 354 TaskSchedulerWorkerTest, |
352 ::testing::Values(2)); | 355 ::testing::Values(2)); |
353 | 356 |
354 namespace { | 357 namespace { |
355 | 358 |
356 class ControllableDetachDelegate : public SchedulerWorkerDefaultDelegate { | 359 class ControllableDetachDelegate : public SchedulerWorkerDefaultDelegate { |
357 public: | 360 public: |
361 class Controls : public RefCountedThreadSafe<Controls> { | |
362 public: | |
363 Controls() | |
364 : work_running_(WaitableEvent::ResetPolicy::MANUAL, | |
365 WaitableEvent::InitialState::SIGNALED), | |
366 work_processed_(WaitableEvent::ResetPolicy::MANUAL, | |
367 WaitableEvent::InitialState::NOT_SIGNALED), | |
368 detach_requested_(WaitableEvent::ResetPolicy::MANUAL, | |
369 WaitableEvent::InitialState::NOT_SIGNALED), | |
370 detached_(WaitableEvent::ResetPolicy::MANUAL, | |
371 WaitableEvent::InitialState::NOT_SIGNALED), | |
372 can_detach_block_(WaitableEvent::ResetPolicy::MANUAL, | |
373 WaitableEvent::InitialState::SIGNALED), | |
374 destroyed_(WaitableEvent::ResetPolicy::MANUAL, | |
375 WaitableEvent::InitialState::NOT_SIGNALED) {} | |
376 | |
377 void HaveWorkBlock() { work_running_.Reset(); } | |
378 | |
379 void UnblockWork() { work_running_.Signal(); } | |
380 | |
381 void MakeCanDetachBlock() { can_detach_block_.Reset(); } | |
382 | |
383 void UnblockCanDetach() { can_detach_block_.Signal(); } | |
384 | |
385 void WaitForWorkToRun() { work_processed_.Wait(); } | |
386 | |
387 void WaitForDetachRequest() { detach_requested_.Wait(); } | |
388 | |
389 void WaitForDetach() { detached_.Wait(); } | |
390 | |
391 void WaitForDelegateDestroy() { destroyed_.Wait(); } | |
392 | |
393 void ResetState() { | |
394 work_running_.Signal(); | |
395 work_processed_.Reset(); | |
396 detach_requested_.Reset(); | |
397 can_detach_block_.Signal(); | |
398 work_requested_ = false; | |
399 } | |
400 | |
401 void set_can_detach(bool can_detach) { can_detach_ = can_detach; } | |
402 | |
403 private: | |
404 friend class ControllableDetachDelegate; | |
405 friend class RefCountedThreadSafe<Controls>; | |
406 ~Controls() = default; | |
407 | |
408 WaitableEvent work_running_; | |
409 WaitableEvent work_processed_; | |
410 WaitableEvent detach_requested_; | |
411 WaitableEvent detached_; | |
412 WaitableEvent can_detach_block_; | |
413 WaitableEvent destroyed_; | |
414 | |
415 bool can_detach_ = false; | |
416 bool work_requested_ = false; | |
417 | |
418 DISALLOW_COPY_AND_ASSIGN(Controls); | |
419 }; | |
420 | |
358 ControllableDetachDelegate(TaskTracker* task_tracker) | 421 ControllableDetachDelegate(TaskTracker* task_tracker) |
359 : task_tracker_(task_tracker), | 422 : task_tracker_(task_tracker), controls_(new Controls()) {} |
360 work_processed_(WaitableEvent::ResetPolicy::MANUAL, | |
361 WaitableEvent::InitialState::NOT_SIGNALED), | |
362 detach_requested_(WaitableEvent::ResetPolicy::MANUAL, | |
363 WaitableEvent::InitialState::NOT_SIGNALED), | |
364 detached_(WaitableEvent::ResetPolicy::MANUAL, | |
365 WaitableEvent::InitialState::NOT_SIGNALED) { | |
366 EXPECT_TRUE(task_tracker_); | |
367 } | |
368 | 423 |
369 ~ControllableDetachDelegate() override = default; | 424 ~ControllableDetachDelegate() override { controls_->destroyed_.Signal(); } |
370 | |
371 // SchedulerWorker::Delegate: | |
372 MOCK_METHOD1(OnMainEntry, void(SchedulerWorker* worker)); | |
373 | 425 |
374 scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) | 426 scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) |
375 override { | 427 override { |
376 // Sends one item of work to signal |work_processed_|. On subsequent calls, | 428 // Sends one item of work to signal |work_processed_|. On subsequent calls, |
377 // sends nullptr to indicate there's no more work to be done. | 429 // sends nullptr to indicate there's no more work to be done. |
378 if (work_requested_) | 430 if (controls_->work_requested_) |
379 return nullptr; | 431 return nullptr; |
380 | 432 |
381 work_requested_ = true; | 433 controls_->work_requested_ = true; |
382 scoped_refptr<Sequence> sequence(new Sequence); | 434 scoped_refptr<Sequence> sequence(new Sequence); |
383 std::unique_ptr<Task> task(new Task( | 435 std::unique_ptr<Task> task(new Task( |
384 FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&work_processed_)), | 436 FROM_HERE, |
385 TaskTraits(), TimeDelta())); | 437 Bind( |
438 [](WaitableEvent* work_processed, WaitableEvent* work_running) { | |
439 work_processed->Signal(); | |
440 work_running->Wait(); | |
441 }, | |
442 Unretained(&controls_->work_processed_), | |
443 Unretained(&controls_->work_running_)), | |
444 TaskTraits().WithBaseSyncPrimitives().WithShutdownBehavior( | |
445 TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN), | |
446 TimeDelta())); | |
386 EXPECT_TRUE(task_tracker_->WillPostTask(task.get())); | 447 EXPECT_TRUE(task_tracker_->WillPostTask(task.get())); |
387 sequence->PushTask(std::move(task)); | 448 sequence->PushTask(std::move(task)); |
388 return sequence; | 449 return sequence; |
389 } | 450 } |
390 | 451 |
391 void DidRunTask() override {} | 452 void DidRunTask() override {} |
392 | 453 |
393 bool CanDetach(SchedulerWorker* worker) override { | 454 bool CanDetach(SchedulerWorker* worker) override { |
394 detach_requested_.Signal(); | 455 // Saving |can_detach_| now so that callers waiting on |detach_requested_| |
395 return can_detach_; | 456 // have the thread go to sleep and then allow detachment. |
457 bool can_detach = controls_->can_detach_; | |
458 controls_->detach_requested_.Signal(); | |
459 controls_->can_detach_block_.Wait(); | |
460 return can_detach; | |
396 } | 461 } |
397 | 462 |
398 void OnDetach() override { | 463 void OnDetach() override { |
399 EXPECT_TRUE(can_detach_); | 464 EXPECT_TRUE(controls_->can_detach_); |
400 EXPECT_TRUE(detach_requested_.IsSignaled()); | 465 EXPECT_TRUE(controls_->detach_requested_.IsSignaled()); |
401 detached_.Signal(); | 466 controls_->detached_.Signal(); |
402 } | 467 } |
403 | 468 |
404 void WaitForWorkToRun() { | 469 // ControllableDetachDelegate: |
gab
2017/02/21 19:01:04
This usually means that it implements that interfa
robliao
2017/02/21 22:26:57
This was habit for me working in C++ interfaces fo
| |
405 work_processed_.Wait(); | 470 scoped_refptr<Controls> controls() { return controls_; } |
gab
2017/02/21 19:01:04
Does this need to expose the ref (usage seems to n
robliao
2017/02/21 22:26:57
This needs to be owned for cases where we race bet
| |
406 } | |
407 | |
408 void WaitForDetachRequest() { | |
409 detach_requested_.Wait(); | |
410 } | |
411 | |
412 void WaitForDetach() { detached_.Wait(); } | |
413 | |
414 void ResetState() { | |
415 work_requested_ = false; | |
416 work_processed_.Reset(); | |
417 detach_requested_.Reset(); | |
418 } | |
419 | |
420 void set_can_detach(bool can_detach) { can_detach_ = can_detach; } | |
421 | 471 |
422 private: | 472 private: |
473 scoped_refptr<Sequence> work_sequence_; | |
423 TaskTracker* const task_tracker_; | 474 TaskTracker* const task_tracker_; |
424 bool work_requested_ = false; | 475 scoped_refptr<Controls> controls_; |
425 bool can_detach_ = false; | |
426 WaitableEvent work_processed_; | |
427 WaitableEvent detach_requested_; | |
428 WaitableEvent detached_; | |
429 | 476 |
430 DISALLOW_COPY_AND_ASSIGN(ControllableDetachDelegate); | 477 DISALLOW_COPY_AND_ASSIGN(ControllableDetachDelegate); |
431 }; | 478 }; |
432 | 479 |
480 class MockedControllableDetachDelegate : public ControllableDetachDelegate { | |
481 public: | |
482 MockedControllableDetachDelegate(TaskTracker* task_tracker) | |
483 : ControllableDetachDelegate(task_tracker){}; | |
484 ~MockedControllableDetachDelegate() = default; | |
485 | |
486 // SchedulerWorker::Delegate: | |
487 MOCK_METHOD1(OnMainEntry, void(SchedulerWorker* worker)); | |
488 | |
489 private: | |
490 DISALLOW_COPY_AND_ASSIGN(MockedControllableDetachDelegate); | |
491 }; | |
492 | |
433 } // namespace | 493 } // namespace |
434 | 494 |
435 TEST(TaskSchedulerWorkerTest, WorkerDetaches) { | 495 TEST(TaskSchedulerWorkerTest, WorkerDetaches) { |
436 TaskTracker task_tracker; | 496 TaskTracker task_tracker; |
437 // Will be owned by SchedulerWorker. | 497 // Will be owned by SchedulerWorker. |
438 ControllableDetachDelegate* delegate = | 498 MockedControllableDetachDelegate* delegate = |
439 new StrictMock<ControllableDetachDelegate>(&task_tracker); | 499 new StrictMock<MockedControllableDetachDelegate>(&task_tracker); |
440 delegate->set_can_detach(true); | 500 scoped_refptr<ControllableDetachDelegate::Controls> controls = |
501 delegate->controls(); | |
502 controls->set_can_detach(true); | |
441 EXPECT_CALL(*delegate, OnMainEntry(_)); | 503 EXPECT_CALL(*delegate, OnMainEntry(_)); |
442 std::unique_ptr<SchedulerWorker> worker = | 504 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( |
443 SchedulerWorker::Create( | 505 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, |
444 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, | 506 SchedulerWorker::InitialState::ALIVE); |
445 SchedulerWorker::InitialState::ALIVE); | 507 worker->WakeUp(); |
446 worker->WakeUp(); | 508 controls->WaitForWorkToRun(); |
447 delegate->WaitForWorkToRun(); | |
448 Mock::VerifyAndClear(delegate); | 509 Mock::VerifyAndClear(delegate); |
449 delegate->WaitForDetachRequest(); | 510 controls->WaitForDetachRequest(); |
450 delegate->WaitForDetach(); | 511 controls->WaitForDetach(); |
451 ASSERT_FALSE(worker->ThreadAliveForTesting()); | 512 ASSERT_FALSE(worker->ThreadAliveForTesting()); |
452 } | 513 } |
453 | 514 |
515 TEST(TaskSchedulerWorkerTest, WorkerReleasesBeforeDetach) { | |
516 TaskTracker task_tracker; | |
517 // Will be owned by SchedulerWorker. | |
518 // No mock here as that's reasonably covered by other tests and the delegate | |
519 // may destroy on a different thread. Mocks aren't designed with that in mind. | |
520 std::unique_ptr<ControllableDetachDelegate> delegate = | |
521 MakeUnique<ControllableDetachDelegate>(&task_tracker); | |
522 scoped_refptr<ControllableDetachDelegate::Controls> controls = | |
523 delegate->controls(); | |
524 | |
525 controls->set_can_detach(true); | |
526 controls->MakeCanDetachBlock(); | |
527 | |
528 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( | |
529 ThreadPriority::NORMAL, std::move(delegate), &task_tracker, | |
530 SchedulerWorker::InitialState::ALIVE); | |
531 worker->WakeUp(); | |
532 | |
533 controls->WaitForDetachRequest(); | |
534 worker->Cleanup(); | |
535 worker = nullptr; | |
536 controls->UnblockCanDetach(); | |
537 controls->WaitForDelegateDestroy(); | |
538 } | |
539 | |
540 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndSelfDestroysAfterDetach) { | |
541 TaskTracker task_tracker; | |
542 // Will be owned by SchedulerWorker. | |
543 // No mock here as that's reasonably covered by other tests and the delegate | |
544 // may destroy on a different thread. Mocks aren't designed with that in mind. | |
545 std::unique_ptr<ControllableDetachDelegate> delegate = | |
546 MakeUnique<ControllableDetachDelegate>(&task_tracker); | |
547 scoped_refptr<ControllableDetachDelegate::Controls> controls = | |
548 delegate->controls(); | |
549 | |
550 controls->set_can_detach(true); | |
551 | |
552 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( | |
553 ThreadPriority::NORMAL, std::move(delegate), &task_tracker, | |
554 SchedulerWorker::InitialState::ALIVE); | |
555 worker->WakeUp(); | |
556 | |
557 controls->WaitForDetach(); | |
558 worker->Cleanup(); | |
559 worker = nullptr; | |
560 controls->WaitForDelegateDestroy(); | |
561 } | |
562 | |
563 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndSelfDestroysDuringWork) { | |
564 TaskTracker task_tracker; | |
565 // Will be owned by SchedulerWorker. | |
566 // No mock here as that's reasonably covered by other tests and the delegate | |
567 // may destroy on a different thread. Mocks aren't designed with that in mind. | |
568 std::unique_ptr<ControllableDetachDelegate> delegate = | |
569 MakeUnique<ControllableDetachDelegate>(&task_tracker); | |
570 scoped_refptr<ControllableDetachDelegate::Controls> controls = | |
571 delegate->controls(); | |
572 | |
573 controls->set_can_detach(true); | |
574 controls->HaveWorkBlock(); | |
575 | |
576 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( | |
577 ThreadPriority::NORMAL, std::move(delegate), &task_tracker, | |
578 SchedulerWorker::InitialState::ALIVE); | |
579 worker->WakeUp(); | |
580 | |
581 controls->WaitForWorkToRun(); | |
582 worker->Cleanup(); | |
583 worker = nullptr; | |
584 controls->UnblockWork(); | |
585 controls->WaitForDelegateDestroy(); | |
586 } | |
587 | |
588 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndSelfDestroysDuringWait) { | |
589 TaskTracker task_tracker; | |
590 // Will be owned by SchedulerWorker. | |
591 // No mock here as that's reasonably covered by other tests and the delegate | |
592 // may destroy on a different thread. Mocks aren't designed with that in mind. | |
593 std::unique_ptr<ControllableDetachDelegate> delegate = | |
594 MakeUnique<ControllableDetachDelegate>(&task_tracker); | |
595 scoped_refptr<ControllableDetachDelegate::Controls> controls = | |
596 delegate->controls(); | |
597 | |
598 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( | |
599 ThreadPriority::NORMAL, std::move(delegate), &task_tracker, | |
600 SchedulerWorker::InitialState::ALIVE); | |
601 worker->WakeUp(); | |
602 | |
603 controls->WaitForDetachRequest(); | |
604 controls->set_can_detach(true); | |
gab
2017/02/21 19:01:04
What's the point of setting it after? (I guess I a
robliao
2017/02/21 22:26:57
In this case, we just want to wait for a CanDetach
| |
605 worker->Cleanup(); | |
606 worker = nullptr; | |
607 controls->WaitForDelegateDestroy(); | |
608 } | |
609 | |
610 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndSelfDestroysDuringShutdown) { | |
611 TaskTracker task_tracker; | |
612 // Will be owned by SchedulerWorker. | |
613 // No mock here as that's reasonably covered by other tests and the delegate | |
614 // may destroy on a different thread. Mocks aren't designed with that in mind. | |
615 std::unique_ptr<ControllableDetachDelegate> delegate = | |
616 MakeUnique<ControllableDetachDelegate>(&task_tracker); | |
617 scoped_refptr<ControllableDetachDelegate::Controls> controls = | |
618 delegate->controls(); | |
619 | |
620 controls->HaveWorkBlock(); | |
621 | |
622 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( | |
623 ThreadPriority::NORMAL, std::move(delegate), &task_tracker, | |
624 SchedulerWorker::InitialState::ALIVE); | |
625 worker->WakeUp(); | |
626 | |
627 controls->WaitForWorkToRun(); | |
628 task_tracker.Shutdown(); | |
629 worker->Cleanup(); | |
630 worker = nullptr; | |
631 controls->UnblockWork(); | |
632 controls->WaitForDelegateDestroy(); | |
633 } | |
634 | |
635 namespace { | |
636 | |
637 class CallJoinFromDifferentThread : public SimpleThread { | |
638 public: | |
639 CallJoinFromDifferentThread(SchedulerWorker* worker_to_join) | |
640 : SimpleThread("SchedulerWorkerJoinThread"), | |
641 worker_to_join_(worker_to_join) {} | |
642 | |
643 ~CallJoinFromDifferentThread() override = default; | |
644 | |
645 void Run() override { worker_to_join_->JoinForTesting(); } | |
646 | |
647 private: | |
648 SchedulerWorker* const worker_to_join_; | |
649 DISALLOW_COPY_AND_ASSIGN(CallJoinFromDifferentThread); | |
650 }; | |
651 | |
652 } // namespace | |
653 | |
654 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndSelfDestroysDuringJoin) { | |
655 TaskTracker task_tracker; | |
656 // Will be owned by SchedulerWorker. | |
657 // No mock here as that's reasonably covered by other tests and the | |
658 // delegate may destroy on a different thread. Mocks aren't designed with that | |
659 // in mind. | |
660 std::unique_ptr<ControllableDetachDelegate> delegate = | |
661 MakeUnique<ControllableDetachDelegate>(&task_tracker); | |
662 scoped_refptr<ControllableDetachDelegate::Controls> controls = | |
663 delegate->controls(); | |
664 | |
665 controls->HaveWorkBlock(); | |
666 | |
667 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( | |
668 ThreadPriority::NORMAL, std::move(delegate), &task_tracker, | |
669 SchedulerWorker::InitialState::ALIVE); | |
670 worker->WakeUp(); | |
671 | |
672 controls->WaitForWorkToRun(); | |
673 CallJoinFromDifferentThread join_from_different_thread(worker.get()); | |
674 join_from_different_thread.Start(); | |
675 // While Start blocks until the thread starts, that doesn't cover the actual | |
gab
2017/02/21 19:01:04
Start no longer blocks until thread starts (Franco
robliao
2017/02/21 22:26:57
SimpleThread::Start() waits.
Thread::Start() does
gab
2017/02/22 18:02:24
Ah, found it: https://codereview.chromium.org/2664
robliao
2017/02/22 20:43:39
Went with the event. Amended comment.
| |
676 // join call. Yield here to give the other thread a chance to call | |
677 // JoinForTesting(). | |
678 PlatformThread::YieldCurrentThread(); | |
679 worker->Cleanup(); | |
680 worker = nullptr; | |
681 controls->UnblockWork(); | |
682 controls->WaitForDelegateDestroy(); | |
683 join_from_different_thread.Join(); | |
684 } | |
685 | |
454 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndWakes) { | 686 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndWakes) { |
455 TaskTracker task_tracker; | 687 TaskTracker task_tracker; |
456 // Will be owned by SchedulerWorker. | 688 // Will be owned by SchedulerWorker. |
457 ControllableDetachDelegate* delegate = | 689 MockedControllableDetachDelegate* delegate = |
458 new StrictMock<ControllableDetachDelegate>(&task_tracker); | 690 new StrictMock<MockedControllableDetachDelegate>(&task_tracker); |
459 delegate->set_can_detach(true); | 691 scoped_refptr<ControllableDetachDelegate::Controls> controls = |
692 delegate->controls(); | |
693 | |
694 controls->set_can_detach(true); | |
460 EXPECT_CALL(*delegate, OnMainEntry(_)); | 695 EXPECT_CALL(*delegate, OnMainEntry(_)); |
461 std::unique_ptr<SchedulerWorker> worker = | 696 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( |
462 SchedulerWorker::Create( | 697 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, |
463 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, | 698 SchedulerWorker::InitialState::ALIVE); |
464 SchedulerWorker::InitialState::ALIVE); | 699 worker->WakeUp(); |
465 worker->WakeUp(); | 700 controls->WaitForWorkToRun(); |
466 delegate->WaitForWorkToRun(); | |
467 Mock::VerifyAndClear(delegate); | 701 Mock::VerifyAndClear(delegate); |
468 delegate->WaitForDetachRequest(); | 702 controls->WaitForDetachRequest(); |
469 delegate->WaitForDetach(); | 703 controls->WaitForDetach(); |
470 ASSERT_FALSE(worker->ThreadAliveForTesting()); | 704 ASSERT_FALSE(worker->ThreadAliveForTesting()); |
471 | 705 |
472 delegate->ResetState(); | 706 controls->ResetState(); |
473 delegate->set_can_detach(false); | 707 controls->set_can_detach(false); |
474 // Expect OnMainEntry() to be called when SchedulerWorker recreates its | 708 // Expect OnMainEntry() to be called when SchedulerWorker recreates its |
475 // thread. | 709 // thread. |
476 EXPECT_CALL(*delegate, OnMainEntry(worker.get())); | 710 EXPECT_CALL(*delegate, OnMainEntry(worker.get())); |
477 worker->WakeUp(); | 711 worker->WakeUp(); |
478 delegate->WaitForWorkToRun(); | 712 controls->WaitForWorkToRun(); |
479 Mock::VerifyAndClear(delegate); | 713 Mock::VerifyAndClear(delegate); |
480 delegate->WaitForDetachRequest(); | 714 controls->WaitForDetachRequest(); |
481 delegate->WaitForDetach(); | 715 controls->WaitForDetach(); |
482 ASSERT_TRUE(worker->ThreadAliveForTesting()); | 716 ASSERT_TRUE(worker->ThreadAliveForTesting()); |
483 worker->JoinForTesting(); | 717 worker->JoinForTesting(); |
484 } | 718 } |
485 | 719 |
486 TEST(TaskSchedulerWorkerTest, CreateDetached) { | 720 TEST(TaskSchedulerWorkerTest, CreateDetached) { |
487 TaskTracker task_tracker; | 721 TaskTracker task_tracker; |
488 // Will be owned by SchedulerWorker. | 722 // Will be owned by SchedulerWorker. |
489 ControllableDetachDelegate* delegate = | 723 MockedControllableDetachDelegate* delegate = |
490 new StrictMock<ControllableDetachDelegate>(&task_tracker); | 724 new StrictMock<MockedControllableDetachDelegate>(&task_tracker); |
491 std::unique_ptr<SchedulerWorker> worker = | 725 scoped_refptr<ControllableDetachDelegate::Controls> controls = |
492 SchedulerWorker::Create( | 726 delegate->controls(); |
493 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, | 727 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( |
494 SchedulerWorker::InitialState::DETACHED); | 728 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, |
729 SchedulerWorker::InitialState::DETACHED); | |
495 ASSERT_FALSE(worker->ThreadAliveForTesting()); | 730 ASSERT_FALSE(worker->ThreadAliveForTesting()); |
496 EXPECT_CALL(*delegate, OnMainEntry(worker.get())); | 731 EXPECT_CALL(*delegate, OnMainEntry(worker.get())); |
497 worker->WakeUp(); | 732 worker->WakeUp(); |
498 delegate->WaitForWorkToRun(); | 733 controls->WaitForWorkToRun(); |
499 Mock::VerifyAndClear(delegate); | 734 Mock::VerifyAndClear(delegate); |
500 delegate->WaitForDetachRequest(); | 735 controls->WaitForDetachRequest(); |
501 ASSERT_TRUE(worker->ThreadAliveForTesting()); | 736 ASSERT_TRUE(worker->ThreadAliveForTesting()); |
502 worker->JoinForTesting(); | 737 worker->JoinForTesting(); |
503 } | 738 } |
504 | 739 |
505 namespace { | 740 namespace { |
506 | 741 |
507 class ExpectThreadPriorityDelegate : public SchedulerWorkerDefaultDelegate { | 742 class ExpectThreadPriorityDelegate : public SchedulerWorkerDefaultDelegate { |
508 public: | 743 public: |
509 ExpectThreadPriorityDelegate() | 744 ExpectThreadPriorityDelegate() |
510 : priority_verified_in_get_work_event_( | 745 : priority_verified_in_get_work_event_( |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
553 TaskTracker task_tracker; | 788 TaskTracker task_tracker; |
554 | 789 |
555 std::unique_ptr<ExpectThreadPriorityDelegate> delegate( | 790 std::unique_ptr<ExpectThreadPriorityDelegate> delegate( |
556 new ExpectThreadPriorityDelegate); | 791 new ExpectThreadPriorityDelegate); |
557 ExpectThreadPriorityDelegate* delegate_raw = delegate.get(); | 792 ExpectThreadPriorityDelegate* delegate_raw = delegate.get(); |
558 delegate_raw->SetExpectedThreadPriority( | 793 delegate_raw->SetExpectedThreadPriority( |
559 PlatformThread::CanIncreaseCurrentThreadPriority() | 794 PlatformThread::CanIncreaseCurrentThreadPriority() |
560 ? ThreadPriority::BACKGROUND | 795 ? ThreadPriority::BACKGROUND |
561 : ThreadPriority::NORMAL); | 796 : ThreadPriority::NORMAL); |
562 | 797 |
563 std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( | 798 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( |
564 ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker, | 799 ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker, |
565 SchedulerWorker::InitialState::ALIVE); | 800 SchedulerWorker::InitialState::ALIVE); |
566 | 801 |
567 // Verify that the initial thread priority is BACKGROUND (or NORMAL if thread | 802 // Verify that the initial thread priority is BACKGROUND (or NORMAL if thread |
568 // priority can't be increased). | 803 // priority can't be increased). |
569 worker->WakeUp(); | 804 worker->WakeUp(); |
570 delegate_raw->WaitForPriorityVerifiedInGetWork(); | 805 delegate_raw->WaitForPriorityVerifiedInGetWork(); |
571 | 806 |
572 // Verify that the thread priority is bumped to NORMAL during shutdown. | 807 // Verify that the thread priority is bumped to NORMAL during shutdown. |
573 delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL); | 808 delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL); |
574 task_tracker.SetHasShutdownStartedForTesting(); | 809 task_tracker.SetHasShutdownStartedForTesting(); |
575 worker->WakeUp(); | 810 worker->WakeUp(); |
576 delegate_raw->WaitForPriorityVerifiedInGetWork(); | 811 delegate_raw->WaitForPriorityVerifiedInGetWork(); |
577 | 812 |
578 worker->JoinForTesting(); | 813 worker->JoinForTesting(); |
579 } | 814 } |
580 | 815 |
581 TEST(TaskSchedulerWorkerTest, BumpPriorityOfDetachedThreadDuringShutdown) { | 816 TEST(TaskSchedulerWorkerTest, BumpPriorityOfDetachedThreadDuringShutdown) { |
582 TaskTracker task_tracker; | 817 TaskTracker task_tracker; |
583 | 818 |
584 std::unique_ptr<ExpectThreadPriorityDelegate> delegate( | 819 std::unique_ptr<ExpectThreadPriorityDelegate> delegate( |
585 new ExpectThreadPriorityDelegate); | 820 new ExpectThreadPriorityDelegate); |
586 ExpectThreadPriorityDelegate* delegate_raw = delegate.get(); | 821 ExpectThreadPriorityDelegate* delegate_raw = delegate.get(); |
587 delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL); | 822 delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL); |
588 | 823 |
589 // Create a DETACHED thread. | 824 // Create a DETACHED thread. |
590 std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( | 825 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( |
591 ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker, | 826 ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker, |
592 SchedulerWorker::InitialState::DETACHED); | 827 SchedulerWorker::InitialState::DETACHED); |
593 | 828 |
594 // Pretend that shutdown has started. | 829 // Pretend that shutdown has started. |
595 task_tracker.SetHasShutdownStartedForTesting(); | 830 task_tracker.SetHasShutdownStartedForTesting(); |
596 | 831 |
597 // Wake up the thread and verify that its priority is NORMAL when | 832 // Wake up the thread and verify that its priority is NORMAL when |
598 // OnMainEntry() and GetWork() are called. | 833 // OnMainEntry() and GetWork() are called. |
599 worker->WakeUp(); | 834 worker->WakeUp(); |
600 delegate_raw->WaitForPriorityVerifiedInGetWork(); | 835 delegate_raw->WaitForPriorityVerifiedInGetWork(); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
676 // COM library wasn't already initialized on the thread. | 911 // COM library wasn't already initialized on the thread. |
677 EXPECT_EQ(S_OK, delegate_raw->coinitialize_hresult()); | 912 EXPECT_EQ(S_OK, delegate_raw->coinitialize_hresult()); |
678 | 913 |
679 worker->JoinForTesting(); | 914 worker->JoinForTesting(); |
680 } | 915 } |
681 | 916 |
682 #endif // defined(OS_WIN) | 917 #endif // defined(OS_WIN) |
683 | 918 |
684 } // namespace internal | 919 } // namespace internal |
685 } // namespace base | 920 } // namespace base |
OLD | NEW |