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

Side by Side Diff: base/task_scheduler/scheduler_worker_unittest.cc

Issue 2692863012: SchedulerWorker Refcounting for Destruction in Production (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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() {
fdoray 2017/02/17 16:43:41 Reset all members in order of declaration?
robliao 2017/02/17 19:24:36 Done.
394 work_requested_ = false;
395 work_running_.Signal();
396 work_processed_.Reset();
397 detach_requested_.Reset();
398 can_detach_block_.Signal();
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:
405 work_processed_.Wait(); 470 scoped_refptr<Controls> controls() { return controls_; }
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 ;
fdoray 2017/02/17 16:43:41 extra ;
robliao 2017/02/17 19:24:36 Done.
486
487 // SchedulerWorker::Delegate:
488 MOCK_METHOD1(OnMainEntry, void(SchedulerWorker* worker));
489
490 private:
491 DISALLOW_COPY_AND_ASSIGN(MockedControllableDetachDelegate);
492 };
493
433 } // namespace 494 } // namespace
434 495
435 TEST(TaskSchedulerWorkerTest, WorkerDetaches) { 496 TEST(TaskSchedulerWorkerTest, WorkerDetaches) {
436 TaskTracker task_tracker; 497 TaskTracker task_tracker;
437 // Will be owned by SchedulerWorker. 498 // Will be owned by SchedulerWorker.
438 ControllableDetachDelegate* delegate = 499 MockedControllableDetachDelegate* delegate =
439 new StrictMock<ControllableDetachDelegate>(&task_tracker); 500 new StrictMock<MockedControllableDetachDelegate>(&task_tracker);
440 delegate->set_can_detach(true); 501 scoped_refptr<ControllableDetachDelegate::Controls> controls =
502 delegate->controls();
503 controls->set_can_detach(true);
441 EXPECT_CALL(*delegate, OnMainEntry(_)); 504 EXPECT_CALL(*delegate, OnMainEntry(_));
442 std::unique_ptr<SchedulerWorker> worker = 505 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
443 SchedulerWorker::Create( 506 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker,
444 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, 507 SchedulerWorker::InitialState::ALIVE);
445 SchedulerWorker::InitialState::ALIVE); 508 worker->WakeUp();
446 worker->WakeUp(); 509 controls->WaitForWorkToRun();
447 delegate->WaitForWorkToRun();
448 Mock::VerifyAndClear(delegate); 510 Mock::VerifyAndClear(delegate);
449 delegate->WaitForDetachRequest(); 511 controls->WaitForDetachRequest();
450 delegate->WaitForDetach(); 512 controls->WaitForDetach();
451 ASSERT_FALSE(worker->ThreadAliveForTesting()); 513 ASSERT_FALSE(worker->ThreadAliveForTesting());
452 } 514 }
453 515
516 TEST(TaskSchedulerWorkerTest, WorkerReleasesBeforeDetach) {
517 TaskTracker task_tracker;
518 // Will be owned by SchedulerWorker.
519 // No mock here as that's reasonably covered by other tests and the delegate
520 // may destroy on a different thread. Mocks aren't designed with that in mind.
521 std::unique_ptr<ControllableDetachDelegate> delegate =
522 MakeUnique<ControllableDetachDelegate>(&task_tracker);
523 scoped_refptr<ControllableDetachDelegate::Controls> controls =
524 delegate->controls();
525
526 controls->set_can_detach(true);
527 controls->MakeCanDetachBlock();
528
529 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
530 ThreadPriority::NORMAL, std::move(delegate), &task_tracker,
531 SchedulerWorker::InitialState::ALIVE);
532 worker->WakeUp();
533
534 controls->WaitForDetachRequest();
535 worker->RequestThreadTermination();
536 worker = nullptr;
537 controls->UnblockCanDetach();
538 controls->WaitForDelegateDestroy();
539 }
540
541 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndSelfDestroysAfterDetach) {
542 TaskTracker task_tracker;
543 // Will be owned by SchedulerWorker.
544 // No mock here as that's reasonably covered by other tests and the delegate
545 // may destroy on a different thread. Mocks aren't designed with that in mind.
546 std::unique_ptr<ControllableDetachDelegate> delegate =
547 MakeUnique<ControllableDetachDelegate>(&task_tracker);
548 scoped_refptr<ControllableDetachDelegate::Controls> controls =
549 delegate->controls();
550
551 controls->set_can_detach(true);
552
553 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
554 ThreadPriority::NORMAL, std::move(delegate), &task_tracker,
555 SchedulerWorker::InitialState::ALIVE);
556 worker->WakeUp();
557
558 controls->WaitForDetach();
559 worker->RequestThreadTermination();
560 worker = nullptr;
561 controls->WaitForDelegateDestroy();
562 }
563
564 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndSelfDestroysDuringWork) {
565 TaskTracker task_tracker;
566 // Will be owned by SchedulerWorker.
567 // No mock here as that's reasonably covered by other tests and the delegate
568 // may destroy on a different thread. Mocks aren't designed with that in mind.
569 std::unique_ptr<ControllableDetachDelegate> delegate =
570 MakeUnique<ControllableDetachDelegate>(&task_tracker);
571 scoped_refptr<ControllableDetachDelegate::Controls> controls =
572 delegate->controls();
573
574 controls->set_can_detach(true);
575 controls->HaveWorkBlock();
576
577 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
578 ThreadPriority::NORMAL, std::move(delegate), &task_tracker,
579 SchedulerWorker::InitialState::ALIVE);
580 worker->WakeUp();
581
582 controls->WaitForWorkToRun();
583 worker->RequestThreadTermination();
584 worker = nullptr;
585 controls->UnblockWork();
586 controls->WaitForDelegateDestroy();
587 }
588
589 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndSelfDestroysDuringWait) {
590 TaskTracker task_tracker;
591 // Will be owned by SchedulerWorker.
592 // No mock here as that's reasonably covered by other tests and the delegate
593 // may destroy on a different thread. Mocks aren't designed with that in mind.
594 std::unique_ptr<ControllableDetachDelegate> delegate =
595 MakeUnique<ControllableDetachDelegate>(&task_tracker);
596 scoped_refptr<ControllableDetachDelegate::Controls> controls =
597 delegate->controls();
598
599 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
600 ThreadPriority::NORMAL, std::move(delegate), &task_tracker,
601 SchedulerWorker::InitialState::ALIVE);
602 worker->WakeUp();
603
604 controls->WaitForDetachRequest();
605 controls->set_can_detach(true);
606 worker->RequestThreadTermination();
607 worker = nullptr;
608 controls->WaitForDelegateDestroy();
609 }
610
611 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndSelfDestroysDuringShutdown) {
612 TaskTracker task_tracker;
613 // Will be owned by SchedulerWorker.
614 // No mock here as that's reasonably covered by other tests and the delegate
615 // may destroy on a different thread. Mocks aren't designed with that in mind.
616 std::unique_ptr<ControllableDetachDelegate> delegate =
617 MakeUnique<ControllableDetachDelegate>(&task_tracker);
618 scoped_refptr<ControllableDetachDelegate::Controls> controls =
619 delegate->controls();
620
621 controls->HaveWorkBlock();
622
623 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
624 ThreadPriority::NORMAL, std::move(delegate), &task_tracker,
625 SchedulerWorker::InitialState::ALIVE);
626 worker->WakeUp();
627
628 controls->WaitForWorkToRun();
629 task_tracker.Shutdown();
630 worker->RequestThreadTermination();
631 worker = nullptr;
632 controls->UnblockWork();
633 controls->WaitForDelegateDestroy();
634 }
635
636 namespace {
637
638 class CallJoinFromDifferentThread : public SimpleThread {
639 public:
640 CallJoinFromDifferentThread(SchedulerWorker* worker_to_join)
641 : SimpleThread("SchedulerWorkerJoinThread"),
642 worker_to_join_(worker_to_join) {}
643
644 ~CallJoinFromDifferentThread() override = default;
645
646 void Run() override { worker_to_join_->JoinForTesting(); }
647
648 private:
649 SchedulerWorker* const worker_to_join_;
650 DISALLOW_COPY_AND_ASSIGN(CallJoinFromDifferentThread);
651 };
652
653 } // namespace
654
655 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndSelfDestroysDuringJoin) {
656 TaskTracker task_tracker;
657 // Will be owned by SchedulerWorker.
658 // No mock here as that's reasonably covered by other tests and the
659 // delegate may destroy on a different thread. Mocks aren't designed with that
660 // in mind.
661 std::unique_ptr<ControllableDetachDelegate> delegate =
662 MakeUnique<ControllableDetachDelegate>(&task_tracker);
663 scoped_refptr<ControllableDetachDelegate::Controls> controls =
664 delegate->controls();
665
666 controls->HaveWorkBlock();
667
668 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
669 ThreadPriority::NORMAL, std::move(delegate), &task_tracker,
670 SchedulerWorker::InitialState::ALIVE);
671 worker->WakeUp();
672
673 controls->WaitForWorkToRun();
674 CallJoinFromDifferentThread join_from_different_thread(worker.get());
675 join_from_different_thread.Start();
676 // While Start blocks until the thread starts, that doesn't cover the actual
677 // join call. Yield here to give the other thread a chance to call
678 // JoinForTesting().
679 PlatformThread::YieldCurrentThread();
680 worker->RequestThreadTermination();
681 worker = nullptr;
682 controls->UnblockWork();
683 controls->WaitForDelegateDestroy();
684 join_from_different_thread.Join();
685 }
686
454 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndWakes) { 687 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndWakes) {
455 TaskTracker task_tracker; 688 TaskTracker task_tracker;
456 // Will be owned by SchedulerWorker. 689 // Will be owned by SchedulerWorker.
457 ControllableDetachDelegate* delegate = 690 MockedControllableDetachDelegate* delegate =
458 new StrictMock<ControllableDetachDelegate>(&task_tracker); 691 new StrictMock<MockedControllableDetachDelegate>(&task_tracker);
459 delegate->set_can_detach(true); 692 scoped_refptr<ControllableDetachDelegate::Controls> controls =
693 delegate->controls();
694
695 controls->set_can_detach(true);
460 EXPECT_CALL(*delegate, OnMainEntry(_)); 696 EXPECT_CALL(*delegate, OnMainEntry(_));
461 std::unique_ptr<SchedulerWorker> worker = 697 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
462 SchedulerWorker::Create( 698 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker,
463 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, 699 SchedulerWorker::InitialState::ALIVE);
464 SchedulerWorker::InitialState::ALIVE); 700 worker->WakeUp();
465 worker->WakeUp(); 701 controls->WaitForWorkToRun();
466 delegate->WaitForWorkToRun();
467 Mock::VerifyAndClear(delegate); 702 Mock::VerifyAndClear(delegate);
468 delegate->WaitForDetachRequest(); 703 controls->WaitForDetachRequest();
469 delegate->WaitForDetach(); 704 controls->WaitForDetach();
470 ASSERT_FALSE(worker->ThreadAliveForTesting()); 705 ASSERT_FALSE(worker->ThreadAliveForTesting());
471 706
472 delegate->ResetState(); 707 controls->ResetState();
473 delegate->set_can_detach(false); 708 controls->set_can_detach(false);
474 // Expect OnMainEntry() to be called when SchedulerWorker recreates its 709 // Expect OnMainEntry() to be called when SchedulerWorker recreates its
475 // thread. 710 // thread.
476 EXPECT_CALL(*delegate, OnMainEntry(worker.get())); 711 EXPECT_CALL(*delegate, OnMainEntry(worker.get()));
477 worker->WakeUp(); 712 worker->WakeUp();
478 delegate->WaitForWorkToRun(); 713 controls->WaitForWorkToRun();
479 Mock::VerifyAndClear(delegate); 714 Mock::VerifyAndClear(delegate);
480 delegate->WaitForDetachRequest(); 715 controls->WaitForDetachRequest();
481 delegate->WaitForDetach(); 716 controls->WaitForDetach();
482 ASSERT_TRUE(worker->ThreadAliveForTesting()); 717 ASSERT_TRUE(worker->ThreadAliveForTesting());
483 worker->JoinForTesting(); 718 worker->JoinForTesting();
484 } 719 }
485 720
486 TEST(TaskSchedulerWorkerTest, CreateDetached) { 721 TEST(TaskSchedulerWorkerTest, CreateDetached) {
487 TaskTracker task_tracker; 722 TaskTracker task_tracker;
488 // Will be owned by SchedulerWorker. 723 // Will be owned by SchedulerWorker.
489 ControllableDetachDelegate* delegate = 724 MockedControllableDetachDelegate* delegate =
490 new StrictMock<ControllableDetachDelegate>(&task_tracker); 725 new StrictMock<MockedControllableDetachDelegate>(&task_tracker);
491 std::unique_ptr<SchedulerWorker> worker = 726 scoped_refptr<ControllableDetachDelegate::Controls> controls =
492 SchedulerWorker::Create( 727 delegate->controls();
493 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, 728 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
494 SchedulerWorker::InitialState::DETACHED); 729 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker,
730 SchedulerWorker::InitialState::DETACHED);
495 ASSERT_FALSE(worker->ThreadAliveForTesting()); 731 ASSERT_FALSE(worker->ThreadAliveForTesting());
496 EXPECT_CALL(*delegate, OnMainEntry(worker.get())); 732 EXPECT_CALL(*delegate, OnMainEntry(worker.get()));
497 worker->WakeUp(); 733 worker->WakeUp();
498 delegate->WaitForWorkToRun(); 734 controls->WaitForWorkToRun();
499 Mock::VerifyAndClear(delegate); 735 Mock::VerifyAndClear(delegate);
500 delegate->WaitForDetachRequest(); 736 controls->WaitForDetachRequest();
501 ASSERT_TRUE(worker->ThreadAliveForTesting()); 737 ASSERT_TRUE(worker->ThreadAliveForTesting());
502 worker->JoinForTesting(); 738 worker->JoinForTesting();
503 } 739 }
504 740
505 namespace { 741 namespace {
506 742
507 class ExpectThreadPriorityDelegate : public SchedulerWorkerDefaultDelegate { 743 class ExpectThreadPriorityDelegate : public SchedulerWorkerDefaultDelegate {
508 public: 744 public:
509 ExpectThreadPriorityDelegate() 745 ExpectThreadPriorityDelegate()
510 : priority_verified_in_get_work_event_( 746 : priority_verified_in_get_work_event_(
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 TaskTracker task_tracker; 789 TaskTracker task_tracker;
554 790
555 std::unique_ptr<ExpectThreadPriorityDelegate> delegate( 791 std::unique_ptr<ExpectThreadPriorityDelegate> delegate(
556 new ExpectThreadPriorityDelegate); 792 new ExpectThreadPriorityDelegate);
557 ExpectThreadPriorityDelegate* delegate_raw = delegate.get(); 793 ExpectThreadPriorityDelegate* delegate_raw = delegate.get();
558 delegate_raw->SetExpectedThreadPriority( 794 delegate_raw->SetExpectedThreadPriority(
559 PlatformThread::CanIncreaseCurrentThreadPriority() 795 PlatformThread::CanIncreaseCurrentThreadPriority()
560 ? ThreadPriority::BACKGROUND 796 ? ThreadPriority::BACKGROUND
561 : ThreadPriority::NORMAL); 797 : ThreadPriority::NORMAL);
562 798
563 std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( 799 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
564 ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker, 800 ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker,
565 SchedulerWorker::InitialState::ALIVE); 801 SchedulerWorker::InitialState::ALIVE);
566 802
567 // Verify that the initial thread priority is BACKGROUND (or NORMAL if thread 803 // Verify that the initial thread priority is BACKGROUND (or NORMAL if thread
568 // priority can't be increased). 804 // priority can't be increased).
569 worker->WakeUp(); 805 worker->WakeUp();
570 delegate_raw->WaitForPriorityVerifiedInGetWork(); 806 delegate_raw->WaitForPriorityVerifiedInGetWork();
571 807
572 // Verify that the thread priority is bumped to NORMAL during shutdown. 808 // Verify that the thread priority is bumped to NORMAL during shutdown.
573 delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL); 809 delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL);
574 task_tracker.SetHasShutdownStartedForTesting(); 810 task_tracker.SetHasShutdownStartedForTesting();
575 worker->WakeUp(); 811 worker->WakeUp();
576 delegate_raw->WaitForPriorityVerifiedInGetWork(); 812 delegate_raw->WaitForPriorityVerifiedInGetWork();
577 813
578 worker->JoinForTesting(); 814 worker->JoinForTesting();
579 } 815 }
580 816
581 TEST(TaskSchedulerWorkerTest, BumpPriorityOfDetachedThreadDuringShutdown) { 817 TEST(TaskSchedulerWorkerTest, BumpPriorityOfDetachedThreadDuringShutdown) {
582 TaskTracker task_tracker; 818 TaskTracker task_tracker;
583 819
584 std::unique_ptr<ExpectThreadPriorityDelegate> delegate( 820 std::unique_ptr<ExpectThreadPriorityDelegate> delegate(
585 new ExpectThreadPriorityDelegate); 821 new ExpectThreadPriorityDelegate);
586 ExpectThreadPriorityDelegate* delegate_raw = delegate.get(); 822 ExpectThreadPriorityDelegate* delegate_raw = delegate.get();
587 delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL); 823 delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL);
588 824
589 // Create a DETACHED thread. 825 // Create a DETACHED thread.
590 std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( 826 scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
591 ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker, 827 ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker,
592 SchedulerWorker::InitialState::DETACHED); 828 SchedulerWorker::InitialState::DETACHED);
593 829
594 // Pretend that shutdown has started. 830 // Pretend that shutdown has started.
595 task_tracker.SetHasShutdownStartedForTesting(); 831 task_tracker.SetHasShutdownStartedForTesting();
596 832
597 // Wake up the thread and verify that its priority is NORMAL when 833 // Wake up the thread and verify that its priority is NORMAL when
598 // OnMainEntry() and GetWork() are called. 834 // OnMainEntry() and GetWork() are called.
599 worker->WakeUp(); 835 worker->WakeUp();
600 delegate_raw->WaitForPriorityVerifiedInGetWork(); 836 delegate_raw->WaitForPriorityVerifiedInGetWork();
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 // COM library wasn't already initialized on the thread. 912 // COM library wasn't already initialized on the thread.
677 EXPECT_EQ(S_OK, delegate_raw->coinitialize_hresult()); 913 EXPECT_EQ(S_OK, delegate_raw->coinitialize_hresult());
678 914
679 worker->JoinForTesting(); 915 worker->JoinForTesting();
680 } 916 }
681 917
682 #endif // defined(OS_WIN) 918 #endif // defined(OS_WIN)
683 919
684 } // namespace internal 920 } // namespace internal
685 } // namespace base 921 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698