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

Side by Side Diff: base/test/scoped_task_scheduler.cc

Issue 2557083002: Run ScopedTaskScheduler tasks synchronously. (Closed)
Patch Set: self-review Created 4 years 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/test/scoped_task_scheduler.h" 5 #include "base/test/scoped_task_scheduler.h"
6 6
7 #include <memory>
8 #include <utility>
7 #include <vector> 9 #include <vector>
8 10
9 #include "base/bind.h" 11 #include "base/bind.h"
10 #include "base/task_scheduler/scheduler_worker_pool_params.h" 12 #include "base/logging.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/metrics/histogram_base.h"
17 #include "base/run_loop.h"
18 #include "base/sequence_token.h"
19 #include "base/sequenced_task_runner.h"
20 #include "base/single_thread_task_runner.h"
21 #include "base/task_runner.h"
22 #include "base/task_scheduler/task.h"
11 #include "base/task_scheduler/task_scheduler.h" 23 #include "base/task_scheduler/task_scheduler.h"
12 #include "base/threading/platform_thread.h" 24 #include "base/task_scheduler/task_tracker.h"
13 #include "base/time/time.h" 25 #include "base/threading/thread_task_runner_handle.h"
14 26
15 namespace base { 27 namespace base {
16 namespace test { 28 namespace test {
17 29
30 namespace {
31
32 enum class ExecutionMode { PARALLEL, SEQUENCED, SINGLE_THREADED };
33
34 class TestTaskScheduler : public TaskScheduler {
35 public:
36 TestTaskScheduler();
37 ~TestTaskScheduler() override;
38
39 // TaskScheduler:
40 void PostTaskWithTraits(const tracked_objects::Location& from_here,
41 const TaskTraits& traits,
42 const Closure& task) override;
43 scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits(
44 const TaskTraits& traits) override;
45 scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits(
46 const TaskTraits& traits) override;
47 scoped_refptr<SingleThreadTaskRunner> CreateSingleThreadTaskRunnerWithTraits(
48 const TaskTraits& traits) override;
49 std::vector<const HistogramBase*> GetHistograms() const override;
50 void Shutdown() override;
51 void FlushForTesting() override;
52
53 // Posts |task| to this TaskScheduler with |sequence_token|. Returns true on
54 // success.
55 bool PostTask(std::unique_ptr<internal::Task> task,
56 const SequenceToken& sequence_token);
57
58 // Runs |task| with |sequence_token| using this TaskScheduler's TaskTracker.
59 void RunTask(std::unique_ptr<internal::Task> task,
60 const SequenceToken& sequence_token);
61
62 // Returns true if this TaskScheduler runs its tasks on the current thread.
63 bool RunsTasksOnCurrentThread() const;
64
65 private:
66 // The MessageLoop created by this TaskScheduler. Nullptr if there was already
67 // a MessageLoop on the thread when this TaskScheduler was created.
68 const std::unique_ptr<MessageLoop> message_loop_ =
69 MessageLoop::current() ? nullptr : MakeUnique<MessageLoop>();
gab 2016/12/09 20:04:17 Not a fan of MessageLoop::current() for all the re
fdoray 2016/12/12 18:18:50 Done.
70
71 // The SingleThreadTaskRunner associated with |message_loop_|.
72 const scoped_refptr<SingleThreadTaskRunner> message_loop_task_runner_ =
73 ThreadTaskRunnerHandle::Get();
74
75 // Handles shutdown behaviors and sets up the environment to run a task.
76 internal::TaskTracker task_tracker_;
77
78 DISALLOW_COPY_AND_ASSIGN(TestTaskScheduler);
79 };
80
81 class TestTaskSchedulerTaskRunner : public SingleThreadTaskRunner {
82 public:
83 TestTaskSchedulerTaskRunner(TestTaskScheduler* task_scheduler,
84 ExecutionMode execution_mode,
85 TaskTraits traits);
86
87 // SingleThreadTaskRunner:
88 bool PostDelayedTask(const tracked_objects::Location& from_here,
89 const Closure& closure,
90 TimeDelta delay) override;
91 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
92 const Closure& closure,
93 TimeDelta delay) override;
94 bool RunsTasksOnCurrentThread() const override;
95
96 private:
97 ~TestTaskSchedulerTaskRunner() override;
98
99 TestTaskScheduler* const task_scheduler_;
100 const ExecutionMode execution_mode_;
101 const SequenceToken sequence_token_;
102 const TaskTraits traits_;
103
104 DISALLOW_COPY_AND_ASSIGN(TestTaskSchedulerTaskRunner);
105 };
106
107 TestTaskScheduler::TestTaskScheduler() = default;
108
109 TestTaskScheduler::~TestTaskScheduler() {
110 // Prevent the RunUntilIdle() call below from running SKIP_ON_SHUTDOWN and
111 // CONTINUE_ON_SHUTDOWN tasks.
112 task_tracker_.SetHasShutdownStartedForTesting();
113
114 // Run pending BLOCK_SHUTDOWN tasks.
115 RunLoop().RunUntilIdle();
116 }
117
118 void TestTaskScheduler::PostTaskWithTraits(
119 const tracked_objects::Location& from_here,
120 const TaskTraits& traits,
121 const Closure& task) {
122 CreateTaskRunnerWithTraits(traits)->PostTask(from_here, task);
123 }
124
125 scoped_refptr<TaskRunner> TestTaskScheduler::CreateTaskRunnerWithTraits(
126 const TaskTraits& traits) {
127 return make_scoped_refptr(
128 new TestTaskSchedulerTaskRunner(this, ExecutionMode::PARALLEL, traits));
129 }
130
131 scoped_refptr<SequencedTaskRunner>
132 TestTaskScheduler::CreateSequencedTaskRunnerWithTraits(
133 const TaskTraits& traits) {
134 return make_scoped_refptr(
135 new TestTaskSchedulerTaskRunner(this, ExecutionMode::SEQUENCED, traits));
136 }
137
138 scoped_refptr<SingleThreadTaskRunner>
139 TestTaskScheduler::CreateSingleThreadTaskRunnerWithTraits(
140 const TaskTraits& traits) {
141 return make_scoped_refptr(new TestTaskSchedulerTaskRunner(
142 this, ExecutionMode::SINGLE_THREADED, traits));
143 }
144
145 std::vector<const HistogramBase*> TestTaskScheduler::GetHistograms() const {
146 NOTREACHED();
147 return std::vector<const HistogramBase*>();
148 }
149
150 void TestTaskScheduler::Shutdown() {
151 NOTREACHED();
152 }
153
154 void TestTaskScheduler::FlushForTesting() {
155 NOTREACHED();
156 }
157
158 bool TestTaskScheduler::PostTask(std::unique_ptr<internal::Task> task,
159 const SequenceToken& sequence_token) {
160 DCHECK(task);
161 if (!task_tracker_.WillPostTask(task.get()))
162 return false;
163 internal::Task* const task_ptr = task.get();
164 return message_loop_task_runner_->PostDelayedTask(
165 task_ptr->posted_from, Bind(&TestTaskScheduler::RunTask, Unretained(this),
166 Passed(std::move(task)), sequence_token),
167 task_ptr->delay);
168 }
169
170 void TestTaskScheduler::RunTask(std::unique_ptr<internal::Task> task,
171 const SequenceToken& sequence_token) {
172 // Clear the MessageLoop TaskRunner to allow TaskTracker to register a
173 // Thread/SequencedTaskRunnerHandle as appropriate.
174 MessageLoop::current()->SetTaskRunner(nullptr);
175
176 // Run the task.
177 task_tracker_.RunTask(std::move(task), sequence_token.IsValid()
178 ? sequence_token
179 : SequenceToken::Create());
180
181 // Restore the MessageLoop TaskRunner.
182 MessageLoop::current()->SetTaskRunner(message_loop_task_runner_);
183 }
184
185 bool TestTaskScheduler::RunsTasksOnCurrentThread() const {
186 return message_loop_task_runner_->RunsTasksOnCurrentThread();
187 }
188
189 TestTaskSchedulerTaskRunner::TestTaskSchedulerTaskRunner(
190 TestTaskScheduler* task_scheduler,
191 ExecutionMode execution_mode,
192 TaskTraits traits)
193 : task_scheduler_(task_scheduler),
194 execution_mode_(execution_mode),
195 sequence_token_(execution_mode == ExecutionMode::PARALLEL
196 ? SequenceToken()
197 : SequenceToken::Create()),
198 traits_(traits) {}
199
200 bool TestTaskSchedulerTaskRunner::PostDelayedTask(
201 const tracked_objects::Location& from_here,
202 const Closure& closure,
203 TimeDelta delay) {
204 auto task = MakeUnique<internal::Task>(from_here, closure, traits_, delay);
205 if (execution_mode_ == ExecutionMode::SEQUENCED)
206 task->sequenced_task_runner_ref = make_scoped_refptr(this);
207 else if (execution_mode_ == ExecutionMode::SINGLE_THREADED)
208 task->single_thread_task_runner_ref = make_scoped_refptr(this);
209 return task_scheduler_->PostTask(std::move(task), sequence_token_);
210 }
211
212 bool TestTaskSchedulerTaskRunner::PostNonNestableDelayedTask(
213 const tracked_objects::Location& from_here,
214 const Closure& closure,
215 TimeDelta delay) {
216 // Tasks are never nested within the task scheduler.
217 return PostDelayedTask(from_here, closure, delay);
218 }
219
220 bool TestTaskSchedulerTaskRunner::RunsTasksOnCurrentThread() const {
221 if (execution_mode_ == ExecutionMode::PARALLEL)
222 return task_scheduler_->RunsTasksOnCurrentThread();
223 return sequence_token_ == SequenceToken::GetForCurrentThread();
224 }
225
226 TestTaskSchedulerTaskRunner::~TestTaskSchedulerTaskRunner() = default;
227
228 } // namespace
229
18 ScopedTaskScheduler::ScopedTaskScheduler() { 230 ScopedTaskScheduler::ScopedTaskScheduler() {
19 DCHECK(!TaskScheduler::GetInstance()); 231 DCHECK(!TaskScheduler::GetInstance());
20 232 TaskScheduler::SetInstance(MakeUnique<TestTaskScheduler>());
21 // Create a TaskScheduler with a single thread to make tests deterministic.
22 constexpr int kMaxThreads = 1;
23 std::vector<SchedulerWorkerPoolParams> worker_pool_params_vector;
24 worker_pool_params_vector.emplace_back(
25 "Simple", ThreadPriority::NORMAL,
26 SchedulerWorkerPoolParams::StandbyThreadPolicy::LAZY, kMaxThreads,
27 TimeDelta::Max());
28 TaskScheduler::CreateAndSetDefaultTaskScheduler(
29 worker_pool_params_vector,
30 Bind([](const TaskTraits&) -> size_t { return 0; }));
31 task_scheduler_ = TaskScheduler::GetInstance(); 233 task_scheduler_ = TaskScheduler::GetInstance();
32 } 234 }
33 235
34 ScopedTaskScheduler::~ScopedTaskScheduler() { 236 ScopedTaskScheduler::~ScopedTaskScheduler() {
237 DCHECK(thread_checker_.CalledOnValidThread());
35 DCHECK_EQ(task_scheduler_, TaskScheduler::GetInstance()); 238 DCHECK_EQ(task_scheduler_, TaskScheduler::GetInstance());
36 TaskScheduler::GetInstance()->Shutdown();
37 TaskScheduler::GetInstance()->JoinForTesting();
38 TaskScheduler::SetInstance(nullptr); 239 TaskScheduler::SetInstance(nullptr);
39 } 240 }
40 241
41 } // namespace test 242 } // namespace test
42 } // namespace base 243 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698