OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "mojo/public/cpp/bindings/tests/thread_per_task_sequenced_task_runner.h
" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/run_loop.h" |
| 10 #include "base/threading/sequenced_task_runner_handle.h" |
| 11 #include "base/threading/simple_thread.h" |
| 12 #include "testing/gtest/include/gtest/gtest.h" |
| 13 |
| 14 namespace mojo { |
| 15 namespace test { |
| 16 |
| 17 class ThreadPerTaskSequencedTaskRunnerOwner::TaskRunnerImpl |
| 18 : public base::SequencedTaskRunner { |
| 19 public: |
| 20 TaskRunnerImpl() |
| 21 : main_runner_(base::SequencedTaskRunnerHandle::Get()), |
| 22 token_(base::SequenceToken::Create()) {} |
| 23 |
| 24 void ShutDown() { |
| 25 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 26 shut_down_ = true; |
| 27 task_queue_.clear(); |
| 28 if (worker_thread_) { |
| 29 worker_thread_->Join(); |
| 30 worker_thread_.reset(); |
| 31 base::RunLoop().RunUntilIdle(); |
| 32 } |
| 33 } |
| 34 |
| 35 bool PostDelayedTask(const tracked_objects::Location& from_here, |
| 36 const base::Closure& task, |
| 37 base::TimeDelta delay) override { |
| 38 return main_runner_->PostTask( |
| 39 FROM_HERE, |
| 40 base::Bind(&TaskRunnerImpl::PostTaskOnMainRunner, this, task)); |
| 41 } |
| 42 |
| 43 bool RunsTasksOnCurrentThread() const override { |
| 44 return base::SequenceToken::GetForCurrentThread() == token_; |
| 45 } |
| 46 |
| 47 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
| 48 const base::Closure& task, |
| 49 base::TimeDelta delay) override { |
| 50 return PostDelayedTask(from_here, task, delay); |
| 51 } |
| 52 |
| 53 private: |
| 54 class WorkerThread : public base::SimpleThread { |
| 55 public: |
| 56 WorkerThread(const base::Closure& task, scoped_refptr<TaskRunnerImpl> owner) |
| 57 : base::SimpleThread("TaskRunnerImpl"), task_(task), owner_(owner) {} |
| 58 |
| 59 private: |
| 60 // base::SimpleThread override. |
| 61 void Run() override { |
| 62 base::ScopedSetSequenceTokenForCurrentThread scoped_token(owner_->token_); |
| 63 base::SequencedTaskRunnerHandle handle(owner_); |
| 64 task_.Run(); |
| 65 owner_->main_runner_->PostTask( |
| 66 FROM_HERE, base::Bind(&TaskRunnerImpl::TaskDone, owner_)); |
| 67 } |
| 68 |
| 69 base::Closure task_; |
| 70 scoped_refptr<TaskRunnerImpl> owner_; |
| 71 }; |
| 72 |
| 73 ~TaskRunnerImpl() override { |
| 74 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 75 DCHECK(shut_down_); |
| 76 DCHECK(!worker_thread_); |
| 77 } |
| 78 |
| 79 void PostTaskOnMainRunner(const base::Closure& task) { |
| 80 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 81 if (shut_down_) |
| 82 return; |
| 83 |
| 84 task_queue_.push_back(task); |
| 85 |
| 86 if (!worker_thread_) |
| 87 StartWorker(); |
| 88 } |
| 89 |
| 90 void TaskDone() { |
| 91 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 92 if (shut_down_) |
| 93 return; |
| 94 |
| 95 worker_thread_->Join(); |
| 96 worker_thread_.reset(); |
| 97 if (task_queue_.empty()) |
| 98 return; |
| 99 |
| 100 StartWorker(); |
| 101 } |
| 102 |
| 103 void StartWorker() { |
| 104 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 105 DCHECK(!worker_thread_); |
| 106 |
| 107 worker_thread_ = base::MakeUnique<WorkerThread>(task_queue_.front(), this); |
| 108 task_queue_.pop_front(); |
| 109 worker_thread_->Start(); |
| 110 } |
| 111 |
| 112 std::deque<base::Closure> task_queue_; |
| 113 |
| 114 base::SequenceChecker sequence_checker_; |
| 115 const scoped_refptr<base::SequencedTaskRunner> main_runner_; |
| 116 const base::SequenceToken token_; |
| 117 std::unique_ptr<base::SimpleThread> worker_thread_; |
| 118 bool shut_down_ = false; |
| 119 }; |
| 120 |
| 121 ThreadPerTaskSequencedTaskRunnerOwner::ThreadPerTaskSequencedTaskRunnerOwner() |
| 122 : task_runner_(new TaskRunnerImpl) {} |
| 123 |
| 124 ThreadPerTaskSequencedTaskRunnerOwner:: |
| 125 ~ThreadPerTaskSequencedTaskRunnerOwner() { |
| 126 task_runner_->ShutDown(); |
| 127 EXPECT_TRUE(task_runner_->HasOneRef()); |
| 128 } |
| 129 |
| 130 scoped_refptr<base::SequencedTaskRunner> |
| 131 ThreadPerTaskSequencedTaskRunnerOwner::GetSequencedTaskRunner() { |
| 132 return task_runner_; |
| 133 } |
| 134 |
| 135 } // namespace test |
| 136 } // namespace mojo |
OLD | NEW |