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

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

Issue 1698183005: Reference CL for the new task scheduler. (Closed) Base URL: https://luckyluke-private.googlesource.com/src@bigmaster2
Patch Set: Created 4 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
« no previous file with comments | « base/task_scheduler/thread_pool.cc ('k') | base/task_scheduler/utils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "base/task_scheduler/thread_pool.h"
6
7 #include "base/bind.h"
8 #include "base/callback_forward.h"
9 #include "base/synchronization/condition_variable.h"
10 #include "base/task_scheduler/scheduler_lock.h"
11 #include "base/task_scheduler/shutdown_manager.h"
12 #include "base/task_scheduler/worker_thread.h"
13 #include "base/threading/platform_thread.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace base {
17 namespace internal {
18
19 namespace {
20 class SingleThreadChecker {
21 public:
22 SingleThreadChecker(const SchedulerLock* predecessor)
23 : ran_all_tasks_on_same_thread_(true),
24 lock_(predecessor) {}
25
26 void RunTask() {
27 AutoSchedulerLock auto_lock(lock_);
28
29 if (!last_thread_handle_.is_null() &&
30 !PlatformThread::CurrentHandle().is_equal(last_thread_handle_)) {
31 ran_all_tasks_on_same_thread_ = false;
32 }
33 last_thread_handle_ = PlatformThread::CurrentHandle();
34 }
35
36 bool ran_all_tasks_on_same_thread() const {
37 return ran_all_tasks_on_same_thread_;
38 }
39
40 private:
41 PlatformThreadHandle last_thread_handle_;
42 bool ran_all_tasks_on_same_thread_;
43 SchedulerLock lock_;
44 };
45 } // namespace
46
47 class TaskSchedulerThreadPoolTest : public testing::Test {
48 protected:
49 TaskSchedulerThreadPoolTest()
50 : thread_pool_(ThreadPool::CreateThreadPool(
51 ThreadPriority::NORMAL,
52 4,
53 Bind(&TaskSchedulerThreadPoolTest::ReinsertSequenceCallback,
54 Unretained(this)),
55 &shutdown_manager_)),
56 cv_(lock_.RawLockForConditionVariable()),
57 last_posted_task_index_(0),
58 last_run_task_index_(0),
59 ran_task_that_should_not_run_(false) {}
60
61 Closure GetTaskThatShouldRunClosure(
62 SingleThreadChecker* single_thread_checker) {
63 ++last_posted_task_index_;
64 return Bind(&TaskSchedulerThreadPoolTest::RunTaskThatShouldRun,
65 Unretained(this), last_posted_task_index_,
66 single_thread_checker);
67 }
68
69 Closure GetTaskThatShouldNotRunClosure() {
70 return Bind(&TaskSchedulerThreadPoolTest::RunTaskThatShouldNotRun,
71 Unretained(this));
72 }
73
74 void WaitUntilLastPostedTaskHasRun() {
75 AutoSchedulerLock auto_lock(lock_);
76 while (last_posted_task_index_ != last_run_task_index_)
77 cv_.Wait();
78 }
79
80 bool ran_task_that_should_not_run() const {
81 return ran_task_that_should_not_run_;
82 }
83
84 const SchedulerLock* lock() {
85 return &lock_;
86 }
87
88 ShutdownManager shutdown_manager_;
89 scoped_ptr<ThreadPool> thread_pool_;
90
91 private:
92 void ReinsertSequenceCallback(scoped_refptr<Sequence> sequence,
93 const WorkerThread* worker_thread) {
94 thread_pool_->ReinsertSequence(sequence, sequence->GetSortKey(),
95 worker_thread);
96 }
97
98 void RunTaskThatShouldRun(size_t index,
99 SingleThreadChecker* single_thread_checker) {
100 AutoSchedulerLock auto_lock(lock_);
101
102 if (single_thread_checker)
103 single_thread_checker->RunTask();
104
105 // Wait until the task with index (|index| - 1) has run. If tasks are
106 // executed in the wrong order, this can block forever and make the test
107 // fail.
108 //
109 // Note: It isn't correct to assume that this condition will always be
110 // immediatly true if tasks are popped from the priority queue in the right
111 // order. Indeed, a thread A could start running task #2 before a thread B
112 // starts running task #1 despite the fact that thread B has popped task #1
113 // before thread A has popped task #2.
114 while (last_run_task_index_ != index - 1)
115 cv_.Wait();
116
117 ++last_run_task_index_;
118 cv_.Broadcast();
119 }
120
121 void RunTaskThatShouldNotRun() { ran_task_that_should_not_run_ = true; }
122
123 // Lock protecting |cv_|.
124 SchedulerLock lock_;
125
126 // Condition variable signaled each time a task completes its execution.
127 ConditionVariable cv_;
128
129 // Index of the last posted task.
130 size_t last_posted_task_index_;
131
132 // Index of the last run task.
133 size_t last_run_task_index_;
134
135 // True if a task that shouldn't run has run.
136 bool ran_task_that_should_not_run_;
137 };
138
139 TEST_F(TaskSchedulerThreadPoolTest, PostSingleParallelTask) {
140 ASSERT_TRUE(thread_pool_.get());
141
142 thread_pool_->CreateTaskRunnerWithTraits(TaskTraits(),
143 ExecutionMode::PARALLEL)
144 ->PostTask(FROM_HERE, GetTaskThatShouldRunClosure(nullptr));
145
146 WaitUntilLastPostedTaskHasRun();
147 thread_pool_->ShutdownAndJoinAllThreadsForTesting();
148 }
149
150 TEST_F(TaskSchedulerThreadPoolTest, PostSingleSequencedTask) {
151 ASSERT_TRUE(thread_pool_.get());
152
153 thread_pool_->CreateTaskRunnerWithTraits(TaskTraits(),
154 ExecutionMode::SEQUENCED)
155 ->PostTask(FROM_HERE, GetTaskThatShouldRunClosure(nullptr));
156
157 WaitUntilLastPostedTaskHasRun();
158 thread_pool_->ShutdownAndJoinAllThreadsForTesting();
159 }
160
161 TEST_F(TaskSchedulerThreadPoolTest, PostSingleSingleThreadedTask) {
162 ASSERT_TRUE(thread_pool_.get());
163
164 thread_pool_->CreateTaskRunnerWithTraits(TaskTraits(),
165 ExecutionMode::SINGLE_THREADED)
166 ->PostTask(FROM_HERE, GetTaskThatShouldRunClosure(nullptr));
167
168 WaitUntilLastPostedTaskHasRun();
169 thread_pool_->ShutdownAndJoinAllThreadsForTesting();
170 }
171
172 TEST_F(TaskSchedulerThreadPoolTest, PostMultipleTasksNoWaitBetweenPosts) {
173 ASSERT_TRUE(thread_pool_.get());
174
175 for (size_t i = 0; i < 100; ++i) {
176 thread_pool_->CreateTaskRunnerWithTraits(TaskTraits(),
177 ExecutionMode::PARALLEL)
178 ->PostTask(FROM_HERE, GetTaskThatShouldRunClosure(nullptr));
179 }
180
181 WaitUntilLastPostedTaskHasRun();
182 thread_pool_->ShutdownAndJoinAllThreadsForTesting();
183 }
184
185 TEST_F(TaskSchedulerThreadPoolTest, PostMultipleTasksWaitBetweenPosts) {
186 ASSERT_TRUE(thread_pool_.get());
187
188 for (size_t i = 0; i < 100; ++i) {
189 thread_pool_->CreateTaskRunnerWithTraits(TaskTraits(),
190 ExecutionMode::PARALLEL)
191 ->PostTask(FROM_HERE, GetTaskThatShouldRunClosure(nullptr));
192 WaitUntilLastPostedTaskHasRun();
193 }
194
195 thread_pool_->ShutdownAndJoinAllThreadsForTesting();
196 }
197
198 TEST_F(TaskSchedulerThreadPoolTest, PostMultipleTasksInSameSequence) {
199 ASSERT_TRUE(thread_pool_.get());
200
201 auto task_runner = thread_pool_->CreateTaskRunnerWithTraits(
202 TaskTraits(), ExecutionMode::SEQUENCED);
203
204 for (size_t i = 0; i < 100; ++i)
205 task_runner->PostTask(FROM_HERE, GetTaskThatShouldRunClosure(nullptr));
206
207 WaitUntilLastPostedTaskHasRun();
208 thread_pool_->ShutdownAndJoinAllThreadsForTesting();
209 }
210
211 TEST_F(TaskSchedulerThreadPoolTest, PostMultipleTasksInTwoSequences) {
212 ASSERT_TRUE(thread_pool_.get());
213
214 auto task_runner_a = thread_pool_->CreateTaskRunnerWithTraits(
215 TaskTraits(), ExecutionMode::SEQUENCED);
216 auto task_runner_b = thread_pool_->CreateTaskRunnerWithTraits(
217 TaskTraits(), ExecutionMode::SEQUENCED);
218
219 for (size_t i = 0; i < 100; ++i) {
220 task_runner_a->PostTask(FROM_HERE, GetTaskThatShouldRunClosure(nullptr));
221 task_runner_b->PostTask(FROM_HERE, GetTaskThatShouldRunClosure(nullptr));
222 }
223
224 WaitUntilLastPostedTaskHasRun();
225 thread_pool_->ShutdownAndJoinAllThreadsForTesting();
226 }
227
228 TEST_F(TaskSchedulerThreadPoolTest, PostMultipleSingleThreadedTasks) {
229 ASSERT_TRUE(thread_pool_.get());
230
231 auto task_runner = thread_pool_->CreateTaskRunnerWithTraits(
232 TaskTraits(), ExecutionMode::SINGLE_THREADED);
233 SingleThreadChecker single_thread_checker(lock());
234
235 for (size_t i = 0; i < 100; ++i) {
236 task_runner->PostTask(FROM_HERE,
237 GetTaskThatShouldRunClosure(&single_thread_checker));
238 }
239
240 WaitUntilLastPostedTaskHasRun();
241 thread_pool_->ShutdownAndJoinAllThreadsForTesting();
242 EXPECT_TRUE(single_thread_checker.ran_all_tasks_on_same_thread());
243 }
244
245 TEST_F(TaskSchedulerThreadPoolTest, PostParallelDelayedTasks) {
246 ASSERT_TRUE(thread_pool_.get());
247
248 auto task_runner = thread_pool_->CreateTaskRunnerWithTraits(
249 TaskTraits(), ExecutionMode::PARALLEL);
250
251 for (size_t i = 0; i < 10; ++i) {
252 task_runner->PostDelayedTask(FROM_HERE,
253 GetTaskThatShouldRunClosure(nullptr),
254 TimeDelta::FromMilliseconds(i * 50));
255 }
256
257 WaitUntilLastPostedTaskHasRun();
258 thread_pool_->ShutdownAndJoinAllThreadsForTesting();
259 }
260
261 TEST_F(TaskSchedulerThreadPoolTest, PostSequencedDelayedTasks) {
262 ASSERT_TRUE(thread_pool_.get());
263
264 auto task_runner = thread_pool_->CreateTaskRunnerWithTraits(
265 TaskTraits(), ExecutionMode::SEQUENCED);
266
267 for (size_t i = 0; i < 10; ++i) {
268 task_runner->PostDelayedTask(FROM_HERE,
269 GetTaskThatShouldRunClosure(nullptr),
270 TimeDelta::FromMilliseconds(i * 50));
271 }
272
273 WaitUntilLastPostedTaskHasRun();
274 thread_pool_->ShutdownAndJoinAllThreadsForTesting();
275 }
276
277 TEST_F(TaskSchedulerThreadPoolTest, ShutdownBehavior) {
278 ASSERT_TRUE(thread_pool_.get());
279
280 shutdown_manager_.set_is_shutting_down_for_testing(true);
281
282 // Post tasks with different shutdown behaviors.
283 thread_pool_->CreateTaskRunnerWithTraits(
284 TaskTraits().WithShutdownBehavior(
285 TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN),
286 ExecutionMode::PARALLEL)
287 ->PostTask(FROM_HERE, GetTaskThatShouldNotRunClosure());
288 thread_pool_->CreateTaskRunnerWithTraits(
289 TaskTraits().WithShutdownBehavior(
290 TaskShutdownBehavior::SKIP_ON_SHUTDOWN),
291 ExecutionMode::PARALLEL)
292 ->PostTask(FROM_HERE, GetTaskThatShouldNotRunClosure());
293 thread_pool_->CreateTaskRunnerWithTraits(
294 TaskTraits().WithShutdownBehavior(
295 TaskShutdownBehavior::BLOCK_SHUTDOWN),
296 ExecutionMode::PARALLEL)
297 ->PostTask(FROM_HERE, GetTaskThatShouldRunClosure(nullptr));
298
299 WaitUntilLastPostedTaskHasRun();
300
301 shutdown_manager_.set_is_shutting_down_for_testing(false);
302 thread_pool_->ShutdownAndJoinAllThreadsForTesting();
303
304 EXPECT_FALSE(ran_task_that_should_not_run());
305 }
306
307 } // namespace internal
308 } // namespace base
OLDNEW
« no previous file with comments | « base/task_scheduler/thread_pool.cc ('k') | base/task_scheduler/utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698