| Index: base/task_scheduler/scheduler_worker_unittest.cc
|
| diff --git a/base/task_scheduler/scheduler_worker_unittest.cc b/base/task_scheduler/scheduler_worker_unittest.cc
|
| index b65d50c07c3fb5db64ba8df08031bc6934ef10a5..b8dea8e7454e5a41c432e49180e893e0e074d788 100644
|
| --- a/base/task_scheduler/scheduler_worker_unittest.cc
|
| +++ b/base/task_scheduler/scheduler_worker_unittest.cc
|
| @@ -13,13 +13,16 @@
|
| #include "base/bind_helpers.h"
|
| #include "base/macros.h"
|
| #include "base/memory/ptr_util.h"
|
| +#include "base/memory/ref_counted.h"
|
| #include "base/synchronization/condition_variable.h"
|
| #include "base/synchronization/waitable_event.h"
|
| #include "base/task_scheduler/scheduler_lock.h"
|
| #include "base/task_scheduler/sequence.h"
|
| #include "base/task_scheduler/task.h"
|
| #include "base/task_scheduler/task_tracker.h"
|
| +#include "base/test/test_timeouts.h"
|
| #include "base/threading/platform_thread.h"
|
| +#include "base/threading/simple_thread.h"
|
| #include "base/time/time.h"
|
| #include "build/build_config.h"
|
| #include "testing/gmock/include/gmock/gmock.h"
|
| @@ -121,7 +124,7 @@ class TaskSchedulerWorkerTest : public testing::TestWithParam<size_t> {
|
| return re_enqueued_sequences_;
|
| }
|
|
|
| - std::unique_ptr<SchedulerWorker> worker_;
|
| + scoped_refptr<SchedulerWorker> worker_;
|
|
|
| private:
|
| class TestSchedulerWorkerDelegate : public SchedulerWorkerDefaultDelegate {
|
| @@ -355,34 +358,92 @@ namespace {
|
|
|
| class ControllableDetachDelegate : public SchedulerWorkerDefaultDelegate {
|
| public:
|
| - ControllableDetachDelegate(TaskTracker* task_tracker)
|
| - : task_tracker_(task_tracker),
|
| - work_processed_(WaitableEvent::ResetPolicy::MANUAL,
|
| - WaitableEvent::InitialState::NOT_SIGNALED),
|
| - detach_requested_(WaitableEvent::ResetPolicy::MANUAL,
|
| + class Controls : public RefCountedThreadSafe<Controls> {
|
| + public:
|
| + Controls()
|
| + : work_running_(WaitableEvent::ResetPolicy::MANUAL,
|
| + WaitableEvent::InitialState::SIGNALED),
|
| + work_processed_(WaitableEvent::ResetPolicy::MANUAL,
|
| WaitableEvent::InitialState::NOT_SIGNALED),
|
| - detached_(WaitableEvent::ResetPolicy::MANUAL,
|
| - WaitableEvent::InitialState::NOT_SIGNALED) {
|
| - EXPECT_TRUE(task_tracker_);
|
| - }
|
| + detach_requested_(WaitableEvent::ResetPolicy::MANUAL,
|
| + WaitableEvent::InitialState::NOT_SIGNALED),
|
| + detached_(WaitableEvent::ResetPolicy::MANUAL,
|
| + WaitableEvent::InitialState::NOT_SIGNALED),
|
| + can_detach_block_(WaitableEvent::ResetPolicy::MANUAL,
|
| + WaitableEvent::InitialState::SIGNALED),
|
| + destroyed_(WaitableEvent::ResetPolicy::MANUAL,
|
| + WaitableEvent::InitialState::NOT_SIGNALED) {}
|
|
|
| - ~ControllableDetachDelegate() override = default;
|
| + void HaveWorkBlock() { work_running_.Reset(); }
|
|
|
| - // SchedulerWorker::Delegate:
|
| - MOCK_METHOD1(OnMainEntry, void(SchedulerWorker* worker));
|
| + void UnblockWork() { work_running_.Signal(); }
|
| +
|
| + void MakeCanDetachBlock() { can_detach_block_.Reset(); }
|
| +
|
| + void UnblockCanDetach() { can_detach_block_.Signal(); }
|
| +
|
| + void WaitForWorkToRun() { work_processed_.Wait(); }
|
| +
|
| + void WaitForDetachRequest() { detach_requested_.Wait(); }
|
| +
|
| + void WaitForDetach() { detached_.Wait(); }
|
| +
|
| + void WaitForDelegateDestroy() { destroyed_.Wait(); }
|
| +
|
| + void ResetState() {
|
| + work_running_.Signal();
|
| + work_processed_.Reset();
|
| + detach_requested_.Reset();
|
| + can_detach_block_.Signal();
|
| + work_requested_ = false;
|
| + }
|
| +
|
| + void set_can_detach(bool can_detach) { can_detach_ = can_detach; }
|
| +
|
| + private:
|
| + friend class ControllableDetachDelegate;
|
| + friend class RefCountedThreadSafe<Controls>;
|
| + ~Controls() = default;
|
| +
|
| + WaitableEvent work_running_;
|
| + WaitableEvent work_processed_;
|
| + WaitableEvent detach_requested_;
|
| + WaitableEvent detached_;
|
| + WaitableEvent can_detach_block_;
|
| + WaitableEvent destroyed_;
|
| +
|
| + bool can_detach_ = false;
|
| + bool work_requested_ = false;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Controls);
|
| + };
|
| +
|
| + ControllableDetachDelegate(TaskTracker* task_tracker)
|
| + : task_tracker_(task_tracker), controls_(new Controls()) {}
|
| +
|
| + ~ControllableDetachDelegate() override { controls_->destroyed_.Signal(); }
|
|
|
| scoped_refptr<Sequence> GetWork(SchedulerWorker* worker)
|
| override {
|
| // Sends one item of work to signal |work_processed_|. On subsequent calls,
|
| // sends nullptr to indicate there's no more work to be done.
|
| - if (work_requested_)
|
| + if (controls_->work_requested_)
|
| return nullptr;
|
|
|
| - work_requested_ = true;
|
| + controls_->work_requested_ = true;
|
| scoped_refptr<Sequence> sequence(new Sequence);
|
| std::unique_ptr<Task> task(new Task(
|
| - FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&work_processed_)),
|
| - TaskTraits(), TimeDelta()));
|
| + FROM_HERE,
|
| + Bind(
|
| + [](WaitableEvent* work_processed, WaitableEvent* work_running) {
|
| + work_processed->Signal();
|
| + work_running->Wait();
|
| + },
|
| + Unretained(&controls_->work_processed_),
|
| + Unretained(&controls_->work_running_)),
|
| + TaskTraits().WithBaseSyncPrimitives().WithShutdownBehavior(
|
| + TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN),
|
| + TimeDelta()));
|
| EXPECT_TRUE(task_tracker_->WillPostTask(task.get()));
|
| sequence->PushTask(std::move(task));
|
| return sequence;
|
| @@ -391,43 +452,42 @@ class ControllableDetachDelegate : public SchedulerWorkerDefaultDelegate {
|
| void DidRunTask() override {}
|
|
|
| bool CanDetach(SchedulerWorker* worker) override {
|
| - detach_requested_.Signal();
|
| - return can_detach_;
|
| + // Saving |can_detach_| now so that callers waiting on |detach_requested_|
|
| + // have the thread go to sleep and then allow detachment.
|
| + bool can_detach = controls_->can_detach_;
|
| + controls_->detach_requested_.Signal();
|
| + controls_->can_detach_block_.Wait();
|
| + return can_detach;
|
| }
|
|
|
| void OnDetach() override {
|
| - EXPECT_TRUE(can_detach_);
|
| - EXPECT_TRUE(detach_requested_.IsSignaled());
|
| - detached_.Signal();
|
| + EXPECT_TRUE(controls_->can_detach_);
|
| + EXPECT_TRUE(controls_->detach_requested_.IsSignaled());
|
| + controls_->detached_.Signal();
|
| }
|
|
|
| - void WaitForWorkToRun() {
|
| - work_processed_.Wait();
|
| - }
|
| + // ControllableDetachDelegate:
|
| + scoped_refptr<Controls> controls() { return controls_; }
|
|
|
| - void WaitForDetachRequest() {
|
| - detach_requested_.Wait();
|
| - }
|
| + private:
|
| + scoped_refptr<Sequence> work_sequence_;
|
| + TaskTracker* const task_tracker_;
|
| + scoped_refptr<Controls> controls_;
|
|
|
| - void WaitForDetach() { detached_.Wait(); }
|
| + DISALLOW_COPY_AND_ASSIGN(ControllableDetachDelegate);
|
| +};
|
|
|
| - void ResetState() {
|
| - work_requested_ = false;
|
| - work_processed_.Reset();
|
| - detach_requested_.Reset();
|
| - }
|
| +class MockedControllableDetachDelegate : public ControllableDetachDelegate {
|
| + public:
|
| + MockedControllableDetachDelegate(TaskTracker* task_tracker)
|
| + : ControllableDetachDelegate(task_tracker){};
|
| + ~MockedControllableDetachDelegate() = default;
|
|
|
| - void set_can_detach(bool can_detach) { can_detach_ = can_detach; }
|
| + // SchedulerWorker::Delegate:
|
| + MOCK_METHOD1(OnMainEntry, void(SchedulerWorker* worker));
|
|
|
| private:
|
| - TaskTracker* const task_tracker_;
|
| - bool work_requested_ = false;
|
| - bool can_detach_ = false;
|
| - WaitableEvent work_processed_;
|
| - WaitableEvent detach_requested_;
|
| - WaitableEvent detached_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ControllableDetachDelegate);
|
| + DISALLOW_COPY_AND_ASSIGN(MockedControllableDetachDelegate);
|
| };
|
|
|
| } // namespace
|
| @@ -435,50 +495,232 @@ class ControllableDetachDelegate : public SchedulerWorkerDefaultDelegate {
|
| TEST(TaskSchedulerWorkerTest, WorkerDetaches) {
|
| TaskTracker task_tracker;
|
| // Will be owned by SchedulerWorker.
|
| - ControllableDetachDelegate* delegate =
|
| - new StrictMock<ControllableDetachDelegate>(&task_tracker);
|
| - delegate->set_can_detach(true);
|
| + MockedControllableDetachDelegate* delegate =
|
| + new StrictMock<MockedControllableDetachDelegate>(&task_tracker);
|
| + scoped_refptr<ControllableDetachDelegate::Controls> controls =
|
| + delegate->controls();
|
| + controls->set_can_detach(true);
|
| EXPECT_CALL(*delegate, OnMainEntry(_));
|
| - std::unique_ptr<SchedulerWorker> worker =
|
| - SchedulerWorker::Create(
|
| - ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker,
|
| - SchedulerWorker::InitialState::ALIVE);
|
| + scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
|
| + ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker,
|
| + SchedulerWorker::InitialState::ALIVE);
|
| worker->WakeUp();
|
| - delegate->WaitForWorkToRun();
|
| + controls->WaitForWorkToRun();
|
| Mock::VerifyAndClear(delegate);
|
| - delegate->WaitForDetachRequest();
|
| - delegate->WaitForDetach();
|
| + controls->WaitForDetachRequest();
|
| + controls->WaitForDetach();
|
| ASSERT_FALSE(worker->ThreadAliveForTesting());
|
| }
|
|
|
| +TEST(TaskSchedulerWorkerTest, WorkerCleanupBeforeDetach) {
|
| + TaskTracker task_tracker;
|
| + // Will be owned by SchedulerWorker.
|
| + // No mock here as that's reasonably covered by other tests and the delegate
|
| + // may destroy on a different thread. Mocks aren't designed with that in mind.
|
| + std::unique_ptr<ControllableDetachDelegate> delegate =
|
| + MakeUnique<ControllableDetachDelegate>(&task_tracker);
|
| + scoped_refptr<ControllableDetachDelegate::Controls> controls =
|
| + delegate->controls();
|
| +
|
| + controls->set_can_detach(true);
|
| + controls->MakeCanDetachBlock();
|
| +
|
| + scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
|
| + ThreadPriority::NORMAL, std::move(delegate), &task_tracker,
|
| + SchedulerWorker::InitialState::ALIVE);
|
| + worker->WakeUp();
|
| +
|
| + controls->WaitForDetachRequest();
|
| + worker->Cleanup();
|
| + worker = nullptr;
|
| + controls->UnblockCanDetach();
|
| + controls->WaitForDelegateDestroy();
|
| +}
|
| +
|
| +TEST(TaskSchedulerWorkerTest, WorkerCleanupAfterDetach) {
|
| + TaskTracker task_tracker;
|
| + // Will be owned by SchedulerWorker.
|
| + // No mock here as that's reasonably covered by other tests and the delegate
|
| + // may destroy on a different thread. Mocks aren't designed with that in mind.
|
| + std::unique_ptr<ControllableDetachDelegate> delegate =
|
| + MakeUnique<ControllableDetachDelegate>(&task_tracker);
|
| + scoped_refptr<ControllableDetachDelegate::Controls> controls =
|
| + delegate->controls();
|
| +
|
| + controls->set_can_detach(true);
|
| +
|
| + scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
|
| + ThreadPriority::NORMAL, std::move(delegate), &task_tracker,
|
| + SchedulerWorker::InitialState::ALIVE);
|
| + worker->WakeUp();
|
| +
|
| + controls->WaitForDetach();
|
| + worker->Cleanup();
|
| + worker = nullptr;
|
| + controls->WaitForDelegateDestroy();
|
| +}
|
| +
|
| +TEST(TaskSchedulerWorkerTest, WorkerCleanupDuringWork) {
|
| + TaskTracker task_tracker;
|
| + // Will be owned by SchedulerWorker.
|
| + // No mock here as that's reasonably covered by other tests and the delegate
|
| + // may destroy on a different thread. Mocks aren't designed with that in mind.
|
| + std::unique_ptr<ControllableDetachDelegate> delegate =
|
| + MakeUnique<ControllableDetachDelegate>(&task_tracker);
|
| + scoped_refptr<ControllableDetachDelegate::Controls> controls =
|
| + delegate->controls();
|
| +
|
| + controls->HaveWorkBlock();
|
| +
|
| + scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
|
| + ThreadPriority::NORMAL, std::move(delegate), &task_tracker,
|
| + SchedulerWorker::InitialState::ALIVE);
|
| + worker->WakeUp();
|
| +
|
| + controls->WaitForWorkToRun();
|
| + worker->Cleanup();
|
| + worker = nullptr;
|
| + controls->UnblockWork();
|
| + controls->WaitForDelegateDestroy();
|
| +}
|
| +
|
| +TEST(TaskSchedulerWorkerTest, WorkerCleanupDuringWait) {
|
| + TaskTracker task_tracker;
|
| + // Will be owned by SchedulerWorker.
|
| + // No mock here as that's reasonably covered by other tests and the delegate
|
| + // may destroy on a different thread. Mocks aren't designed with that in mind.
|
| + std::unique_ptr<ControllableDetachDelegate> delegate =
|
| + MakeUnique<ControllableDetachDelegate>(&task_tracker);
|
| + scoped_refptr<ControllableDetachDelegate::Controls> controls =
|
| + delegate->controls();
|
| +
|
| + scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
|
| + ThreadPriority::NORMAL, std::move(delegate), &task_tracker,
|
| + SchedulerWorker::InitialState::ALIVE);
|
| + worker->WakeUp();
|
| +
|
| + controls->WaitForDetachRequest();
|
| + worker->Cleanup();
|
| + worker = nullptr;
|
| + controls->WaitForDelegateDestroy();
|
| +}
|
| +
|
| +TEST(TaskSchedulerWorkerTest, WorkerCleanupDuringShutdown) {
|
| + TaskTracker task_tracker;
|
| + // Will be owned by SchedulerWorker.
|
| + // No mock here as that's reasonably covered by other tests and the delegate
|
| + // may destroy on a different thread. Mocks aren't designed with that in mind.
|
| + std::unique_ptr<ControllableDetachDelegate> delegate =
|
| + MakeUnique<ControllableDetachDelegate>(&task_tracker);
|
| + scoped_refptr<ControllableDetachDelegate::Controls> controls =
|
| + delegate->controls();
|
| +
|
| + controls->HaveWorkBlock();
|
| +
|
| + scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
|
| + ThreadPriority::NORMAL, std::move(delegate), &task_tracker,
|
| + SchedulerWorker::InitialState::ALIVE);
|
| + worker->WakeUp();
|
| +
|
| + controls->WaitForWorkToRun();
|
| + task_tracker.Shutdown();
|
| + worker->Cleanup();
|
| + worker = nullptr;
|
| + controls->UnblockWork();
|
| + controls->WaitForDelegateDestroy();
|
| +}
|
| +
|
| +namespace {
|
| +
|
| +class CallJoinFromDifferentThread : public SimpleThread {
|
| + public:
|
| + CallJoinFromDifferentThread(SchedulerWorker* worker_to_join)
|
| + : SimpleThread("SchedulerWorkerJoinThread"),
|
| + worker_to_join_(worker_to_join),
|
| + run_started_event_(WaitableEvent::ResetPolicy::MANUAL,
|
| + WaitableEvent::InitialState::NOT_SIGNALED) {}
|
| +
|
| + ~CallJoinFromDifferentThread() override = default;
|
| +
|
| + void Run() override {
|
| + run_started_event_.Signal();
|
| + worker_to_join_->JoinForTesting();
|
| + }
|
| +
|
| + void WaitForRunToStart() { run_started_event_.Wait(); }
|
| +
|
| + private:
|
| + SchedulerWorker* const worker_to_join_;
|
| + WaitableEvent run_started_event_;
|
| + DISALLOW_COPY_AND_ASSIGN(CallJoinFromDifferentThread);
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +TEST(TaskSchedulerWorkerTest, WorkerCleanupDuringJoin) {
|
| + TaskTracker task_tracker;
|
| + // Will be owned by SchedulerWorker.
|
| + // No mock here as that's reasonably covered by other tests and the
|
| + // delegate may destroy on a different thread. Mocks aren't designed with that
|
| + // in mind.
|
| + std::unique_ptr<ControllableDetachDelegate> delegate =
|
| + MakeUnique<ControllableDetachDelegate>(&task_tracker);
|
| + scoped_refptr<ControllableDetachDelegate::Controls> controls =
|
| + delegate->controls();
|
| +
|
| + controls->HaveWorkBlock();
|
| +
|
| + scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
|
| + ThreadPriority::NORMAL, std::move(delegate), &task_tracker,
|
| + SchedulerWorker::InitialState::ALIVE);
|
| + worker->WakeUp();
|
| +
|
| + controls->WaitForWorkToRun();
|
| + CallJoinFromDifferentThread join_from_different_thread(worker.get());
|
| + join_from_different_thread.Start();
|
| + join_from_different_thread.WaitForRunToStart();
|
| + // Sleep here to give the other thread a chance to call JoinForTesting().
|
| + // Receiving a signal that Run() was called doesn't mean JoinForTesting() was
|
| + // necessarily called, and we can't signal after JoinForTesting() as
|
| + // JoinForTesting() blocks until we call UnblockWork().
|
| + PlatformThread::Sleep(TestTimeouts::tiny_timeout());
|
| + worker->Cleanup();
|
| + worker = nullptr;
|
| + controls->UnblockWork();
|
| + controls->WaitForDelegateDestroy();
|
| + join_from_different_thread.Join();
|
| +}
|
| +
|
| TEST(TaskSchedulerWorkerTest, WorkerDetachesAndWakes) {
|
| TaskTracker task_tracker;
|
| // Will be owned by SchedulerWorker.
|
| - ControllableDetachDelegate* delegate =
|
| - new StrictMock<ControllableDetachDelegate>(&task_tracker);
|
| - delegate->set_can_detach(true);
|
| + MockedControllableDetachDelegate* delegate =
|
| + new StrictMock<MockedControllableDetachDelegate>(&task_tracker);
|
| + scoped_refptr<ControllableDetachDelegate::Controls> controls =
|
| + delegate->controls();
|
| +
|
| + controls->set_can_detach(true);
|
| EXPECT_CALL(*delegate, OnMainEntry(_));
|
| - std::unique_ptr<SchedulerWorker> worker =
|
| - SchedulerWorker::Create(
|
| - ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker,
|
| - SchedulerWorker::InitialState::ALIVE);
|
| + scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
|
| + ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker,
|
| + SchedulerWorker::InitialState::ALIVE);
|
| worker->WakeUp();
|
| - delegate->WaitForWorkToRun();
|
| + controls->WaitForWorkToRun();
|
| Mock::VerifyAndClear(delegate);
|
| - delegate->WaitForDetachRequest();
|
| - delegate->WaitForDetach();
|
| + controls->WaitForDetachRequest();
|
| + controls->WaitForDetach();
|
| ASSERT_FALSE(worker->ThreadAliveForTesting());
|
|
|
| - delegate->ResetState();
|
| - delegate->set_can_detach(false);
|
| + controls->ResetState();
|
| + controls->set_can_detach(false);
|
| // Expect OnMainEntry() to be called when SchedulerWorker recreates its
|
| // thread.
|
| EXPECT_CALL(*delegate, OnMainEntry(worker.get()));
|
| worker->WakeUp();
|
| - delegate->WaitForWorkToRun();
|
| + controls->WaitForWorkToRun();
|
| Mock::VerifyAndClear(delegate);
|
| - delegate->WaitForDetachRequest();
|
| - delegate->WaitForDetach();
|
| + controls->WaitForDetachRequest();
|
| + controls->WaitForDetach();
|
| ASSERT_TRUE(worker->ThreadAliveForTesting());
|
| worker->JoinForTesting();
|
| }
|
| @@ -486,18 +728,19 @@ TEST(TaskSchedulerWorkerTest, WorkerDetachesAndWakes) {
|
| TEST(TaskSchedulerWorkerTest, CreateDetached) {
|
| TaskTracker task_tracker;
|
| // Will be owned by SchedulerWorker.
|
| - ControllableDetachDelegate* delegate =
|
| - new StrictMock<ControllableDetachDelegate>(&task_tracker);
|
| - std::unique_ptr<SchedulerWorker> worker =
|
| - SchedulerWorker::Create(
|
| - ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker,
|
| - SchedulerWorker::InitialState::DETACHED);
|
| + MockedControllableDetachDelegate* delegate =
|
| + new StrictMock<MockedControllableDetachDelegate>(&task_tracker);
|
| + scoped_refptr<ControllableDetachDelegate::Controls> controls =
|
| + delegate->controls();
|
| + scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
|
| + ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker,
|
| + SchedulerWorker::InitialState::DETACHED);
|
| ASSERT_FALSE(worker->ThreadAliveForTesting());
|
| EXPECT_CALL(*delegate, OnMainEntry(worker.get()));
|
| worker->WakeUp();
|
| - delegate->WaitForWorkToRun();
|
| + controls->WaitForWorkToRun();
|
| Mock::VerifyAndClear(delegate);
|
| - delegate->WaitForDetachRequest();
|
| + controls->WaitForDetachRequest();
|
| ASSERT_TRUE(worker->ThreadAliveForTesting());
|
| worker->JoinForTesting();
|
| }
|
| @@ -560,7 +803,7 @@ TEST(TaskSchedulerWorkerTest, BumpPriorityOfAliveThreadDuringShutdown) {
|
| ? ThreadPriority::BACKGROUND
|
| : ThreadPriority::NORMAL);
|
|
|
| - std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create(
|
| + scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
|
| ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker,
|
| SchedulerWorker::InitialState::ALIVE);
|
|
|
| @@ -587,7 +830,7 @@ TEST(TaskSchedulerWorkerTest, BumpPriorityOfDetachedThreadDuringShutdown) {
|
| delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL);
|
|
|
| // Create a DETACHED thread.
|
| - std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create(
|
| + scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create(
|
| ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker,
|
| SchedulerWorker::InitialState::DETACHED);
|
|
|
|
|