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

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

Issue 2692863012: SchedulerWorker Refcounting for Destruction in Production (Closed)
Patch Set: Fix Up Comments and Description 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() {
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698