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

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

Issue 2019763002: TaskScheduler: Atomic operations in TaskTracker (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: CR gab #26 Created 4 years, 6 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/task_tracker.h" 5 #include "base/task_scheduler/task_tracker.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <vector>
8 9
9 #include "base/bind.h" 10 #include "base/bind.h"
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "base/macros.h" 12 #include "base/macros.h"
12 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
13 #include "base/memory/ref_counted.h" 14 #include "base/memory/ref_counted.h"
14 #include "base/sequenced_task_runner.h" 15 #include "base/sequenced_task_runner.h"
15 #include "base/single_thread_task_runner.h" 16 #include "base/single_thread_task_runner.h"
16 #include "base/synchronization/waitable_event.h" 17 #include "base/synchronization/waitable_event.h"
18 #include "base/task_scheduler/scheduler_lock.h"
17 #include "base/task_scheduler/task.h" 19 #include "base/task_scheduler/task.h"
18 #include "base/task_scheduler/task_traits.h" 20 #include "base/task_scheduler/task_traits.h"
19 #include "base/task_scheduler/test_utils.h" 21 #include "base/task_scheduler/test_utils.h"
20 #include "base/test/test_simple_task_runner.h" 22 #include "base/test/test_simple_task_runner.h"
21 #include "base/threading/platform_thread.h" 23 #include "base/threading/platform_thread.h"
22 #include "base/threading/sequenced_task_runner_handle.h" 24 #include "base/threading/sequenced_task_runner_handle.h"
23 #include "base/threading/simple_thread.h" 25 #include "base/threading/simple_thread.h"
24 #include "base/threading/thread_restrictions.h" 26 #include "base/threading/thread_restrictions.h"
25 #include "base/threading/thread_task_runner_handle.h" 27 #include "base/threading/thread_task_runner_handle.h"
26 #include "testing/gtest/include/gtest/gtest.h" 28 #include "testing/gtest/include/gtest/gtest.h"
27 29
28 namespace base { 30 namespace base {
29 namespace internal { 31 namespace internal {
30 32
31 namespace { 33 namespace {
32 34
35 constexpr size_t kLoadTestNumIterations = 100;
36
33 // Calls TaskTracker::Shutdown() asynchronously. 37 // Calls TaskTracker::Shutdown() asynchronously.
34 class ThreadCallingShutdown : public SimpleThread { 38 class ThreadCallingShutdown : public SimpleThread {
35 public: 39 public:
36 explicit ThreadCallingShutdown(TaskTracker* tracker) 40 explicit ThreadCallingShutdown(TaskTracker* tracker)
37 : SimpleThread("ThreadCallingShutdown"), 41 : SimpleThread("ThreadCallingShutdown"),
38 tracker_(tracker), 42 tracker_(tracker),
39 has_returned_(WaitableEvent::ResetPolicy::MANUAL, 43 has_returned_(WaitableEvent::ResetPolicy::MANUAL,
40 WaitableEvent::InitialState::NOT_SIGNALED) {} 44 WaitableEvent::InitialState::NOT_SIGNALED) {}
41 45
42 // Returns true once the async call to Shutdown() has returned. 46 // Returns true once the async call to Shutdown() has returned.
43 bool has_returned() { return has_returned_.IsSignaled(); } 47 bool has_returned() { return has_returned_.IsSignaled(); }
44 48
45 private: 49 private:
46 void Run() override { 50 void Run() override {
47 tracker_->Shutdown(); 51 tracker_->Shutdown();
48 has_returned_.Signal(); 52 has_returned_.Signal();
49 } 53 }
50 54
51 TaskTracker* const tracker_; 55 TaskTracker* const tracker_;
52 WaitableEvent has_returned_; 56 WaitableEvent has_returned_;
53 57
54 DISALLOW_COPY_AND_ASSIGN(ThreadCallingShutdown); 58 DISALLOW_COPY_AND_ASSIGN(ThreadCallingShutdown);
55 }; 59 };
56 60
57 // Runs a task asynchronously. 61 class ThreadPostingAndRunningTask : public SimpleThread {
58 class ThreadRunningTask : public SimpleThread {
59 public: 62 public:
60 ThreadRunningTask(TaskTracker* tracker, const Task* task) 63 enum Action {
robliao 2016/06/20 21:32:20 Nit: enum class.
fdoray 2016/06/29 18:22:37 Done.
61 : SimpleThread("ThreadRunningTask"), tracker_(tracker), task_(task) {} 64 WILL_POST = 0x1,
65 RUN = 0x2,
66 WILL_POST_AND_RUN = WILL_POST | RUN,
67 };
68
69 ThreadPostingAndRunningTask(TaskTracker* tracker,
70 const Task* task,
71 Action action,
72 bool expect_post_succeeds)
73 : SimpleThread("ThreadPostingAndRunningTask"),
74 tracker_(tracker),
75 task_(task),
76 action_(action),
77 expect_post_succeeds_(expect_post_succeeds) {}
62 78
63 private: 79 private:
64 void Run() override { tracker_->RunTask(task_); } 80 void Run() override {
81 bool post_succeeded = true;
82 if (action_ & WILL_POST) {
83 post_succeeded = tracker_->WillPostTask(task_);
84 EXPECT_EQ(expect_post_succeeds_, post_succeeded);
85 }
86 if (post_succeeded && action_ & RUN)
87 tracker_->RunTask(task_);
88 }
65 89
66 TaskTracker* const tracker_; 90 TaskTracker* const tracker_;
67 const Task* const task_; 91 const Task* const task_;
92 const Action action_;
93 const bool expect_post_succeeds_;
68 94
69 DISALLOW_COPY_AND_ASSIGN(ThreadRunningTask); 95 DISALLOW_COPY_AND_ASSIGN(ThreadPostingAndRunningTask);
70 }; 96 };
71 97
72 class ScopedSetSingletonAllowed { 98 class ScopedSetSingletonAllowed {
73 public: 99 public:
74 ScopedSetSingletonAllowed(bool singleton_allowed) 100 ScopedSetSingletonAllowed(bool singleton_allowed)
75 : previous_value_( 101 : previous_value_(
76 ThreadRestrictions::SetSingletonAllowed(singleton_allowed)) {} 102 ThreadRestrictions::SetSingletonAllowed(singleton_allowed)) {}
77 ~ScopedSetSingletonAllowed() { 103 ~ScopedSetSingletonAllowed() {
78 ThreadRestrictions::SetSingletonAllowed(previous_value_); 104 ThreadRestrictions::SetSingletonAllowed(previous_value_);
79 } 105 }
(...skipping 16 matching lines...) Expand all
96 } 122 }
97 123
98 // Calls tracker_->Shutdown() on a new thread. When this returns, Shutdown() 124 // Calls tracker_->Shutdown() on a new thread. When this returns, Shutdown()
99 // method has been entered on the new thread, but it hasn't necessarily 125 // method has been entered on the new thread, but it hasn't necessarily
100 // returned. 126 // returned.
101 void CallShutdownAsync() { 127 void CallShutdownAsync() {
102 ASSERT_FALSE(thread_calling_shutdown_); 128 ASSERT_FALSE(thread_calling_shutdown_);
103 thread_calling_shutdown_.reset(new ThreadCallingShutdown(&tracker_)); 129 thread_calling_shutdown_.reset(new ThreadCallingShutdown(&tracker_));
104 thread_calling_shutdown_->Start(); 130 thread_calling_shutdown_->Start();
105 while (!tracker_.IsShuttingDownForTesting() && 131 while (!tracker_.IsShuttingDownForTesting() &&
106 !tracker_.shutdown_completed()) { 132 !tracker_.ShutdownCompleted()) {
107 PlatformThread::YieldCurrentThread(); 133 PlatformThread::YieldCurrentThread();
108 } 134 }
109 } 135 }
110 136
111 void WaitForAsyncShutdownCompleted() { 137 void WaitForAsyncShutdownCompleted() {
112 ASSERT_TRUE(thread_calling_shutdown_); 138 ASSERT_TRUE(thread_calling_shutdown_);
113 thread_calling_shutdown_->Join(); 139 thread_calling_shutdown_->Join();
114 EXPECT_TRUE(thread_calling_shutdown_->has_returned()); 140 EXPECT_TRUE(thread_calling_shutdown_->has_returned());
115 EXPECT_TRUE(tracker_.shutdown_completed()); 141 EXPECT_TRUE(tracker_.ShutdownCompleted());
116 } 142 }
117 143
118 void VerifyAsyncShutdownInProgress() { 144 void VerifyAsyncShutdownInProgress() {
119 ASSERT_TRUE(thread_calling_shutdown_); 145 ASSERT_TRUE(thread_calling_shutdown_);
120 EXPECT_FALSE(thread_calling_shutdown_->has_returned()); 146 EXPECT_FALSE(thread_calling_shutdown_->has_returned());
121 EXPECT_FALSE(tracker_.shutdown_completed()); 147 EXPECT_FALSE(tracker_.ShutdownCompleted());
122 EXPECT_TRUE(tracker_.IsShuttingDownForTesting()); 148 EXPECT_TRUE(tracker_.IsShuttingDownForTesting());
123 } 149 }
124 150
151 size_t NumTasksExecuted() {
152 AutoSchedulerLock auto_lock(lock_);
153 return num_tasks_executed_;
154 }
155
125 TaskTracker tracker_; 156 TaskTracker tracker_;
126 size_t num_tasks_executed_ = 0;
127 157
128 private: 158 private:
129 void RunTaskCallback() { ++num_tasks_executed_; } 159 void RunTaskCallback() {
160 AutoSchedulerLock auto_lock(lock_);
161 ++num_tasks_executed_;
162 }
130 163
131 std::unique_ptr<ThreadCallingShutdown> thread_calling_shutdown_; 164 std::unique_ptr<ThreadCallingShutdown> thread_calling_shutdown_;
132 165
166 // Synchronizes accesses to |num_tasks_executed_|.
167 SchedulerLock lock_;
168
169 size_t num_tasks_executed_ = 0;
170
133 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerTaskTrackerTest); 171 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerTaskTrackerTest);
134 }; 172 };
135 173
136 #define WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED() \ 174 #define WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED() \
137 do { \ 175 do { \
138 SCOPED_TRACE(""); \ 176 SCOPED_TRACE(""); \
139 WaitForAsyncShutdownCompleted(); \ 177 WaitForAsyncShutdownCompleted(); \
140 } while (false) 178 } while (false)
141 179
142 #define VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS() \ 180 #define VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS() \
143 do { \ 181 do { \
144 SCOPED_TRACE(""); \ 182 SCOPED_TRACE(""); \
145 VerifyAsyncShutdownInProgress(); \ 183 VerifyAsyncShutdownInProgress(); \
146 } while (false) 184 } while (false)
147 185
148 } // namespace 186 } // namespace
149 187
150 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunBeforeShutdown) { 188 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunBeforeShutdown) {
151 std::unique_ptr<Task> task(CreateTask(GetParam())); 189 std::unique_ptr<Task> task(CreateTask(GetParam()));
152 190
153 // Inform |task_tracker_| that |task| will be posted. 191 // Inform |task_tracker_| that |task| will be posted.
154 EXPECT_TRUE(tracker_.WillPostTask(task.get())); 192 EXPECT_TRUE(tracker_.WillPostTask(task.get()));
155 193
156 // Run the task. 194 // Run the task.
157 EXPECT_EQ(0U, num_tasks_executed_); 195 EXPECT_EQ(0U, NumTasksExecuted());
158 tracker_.RunTask(task.get()); 196 tracker_.RunTask(task.get());
159 EXPECT_EQ(1U, num_tasks_executed_); 197 EXPECT_EQ(1U, NumTasksExecuted());
160 198
161 // Shutdown() shouldn't block. 199 // Shutdown() shouldn't block.
162 tracker_.Shutdown(); 200 tracker_.Shutdown();
163 } 201 }
164 202
165 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunLongTaskBeforeShutdown) { 203 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunLongTaskBeforeShutdown) {
166 // Create a task that will block until |event| is signaled. 204 // Create a task that will block until |event| is signaled.
167 WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC, 205 WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
168 WaitableEvent::InitialState::NOT_SIGNALED); 206 WaitableEvent::InitialState::NOT_SIGNALED);
169 std::unique_ptr<Task> blocked_task( 207 std::unique_ptr<Task> blocked_task(
170 new Task(FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&event)), 208 new Task(FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&event)),
171 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); 209 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()));
172 210
173 // Inform |task_tracker_| that |blocked_task| will be posted. 211 // Inform |task_tracker_| that |blocked_task| will be posted.
174 EXPECT_TRUE(tracker_.WillPostTask(blocked_task.get())); 212 EXPECT_TRUE(tracker_.WillPostTask(blocked_task.get()));
175 213
176 // Run the task asynchronouly. 214 // Run the task asynchronouly.
177 ThreadRunningTask thread_running_task(&tracker_, blocked_task.get()); 215 ThreadPostingAndRunningTask thread_running_task(
216 &tracker_, blocked_task.get(), ThreadPostingAndRunningTask::RUN, false);
178 thread_running_task.Start(); 217 thread_running_task.Start();
179 218
180 // Initiate shutdown while the task is running. 219 // Initiate shutdown while the task is running.
181 CallShutdownAsync(); 220 CallShutdownAsync();
182 221
183 if (GetParam() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) { 222 if (GetParam() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) {
184 // Shutdown should complete even with a CONTINUE_ON_SHUTDOWN in progress. 223 // Shutdown should complete even with a CONTINUE_ON_SHUTDOWN in progress.
185 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); 224 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
186 } else { 225 } else {
187 // Shutdown should block with any non CONTINUE_ON_SHUTDOWN task in progress. 226 // Shutdown should block with any non CONTINUE_ON_SHUTDOWN task in progress.
(...skipping 19 matching lines...) Expand all
207 std::unique_ptr<Task> block_shutdown_task( 246 std::unique_ptr<Task> block_shutdown_task(
208 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); 247 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
209 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); 248 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get()));
210 249
211 // Call Shutdown() asynchronously. 250 // Call Shutdown() asynchronously.
212 CallShutdownAsync(); 251 CallShutdownAsync();
213 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); 252 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
214 253
215 // Try to run |task|. It should only run it it's BLOCK_SHUTDOWN. Otherwise it 254 // Try to run |task|. It should only run it it's BLOCK_SHUTDOWN. Otherwise it
216 // should be discarded. 255 // should be discarded.
217 EXPECT_EQ(0U, num_tasks_executed_); 256 EXPECT_EQ(0U, NumTasksExecuted());
218 tracker_.RunTask(task.get()); 257 tracker_.RunTask(task.get());
219 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 1U : 0U, 258 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 1U : 0U,
220 num_tasks_executed_); 259 NumTasksExecuted());
221 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); 260 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
222 261
223 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task. 262 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task.
224 tracker_.RunTask(block_shutdown_task.get()); 263 tracker_.RunTask(block_shutdown_task.get());
225 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, 264 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U,
226 num_tasks_executed_); 265 NumTasksExecuted());
227 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); 266 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
228 } 267 }
229 268
230 TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) { 269 TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) {
231 // Inform |task_tracker_| that a task will be posted. 270 // Inform |task_tracker_| that a task will be posted.
232 std::unique_ptr<Task> task(CreateTask(GetParam())); 271 std::unique_ptr<Task> task(CreateTask(GetParam()));
233 EXPECT_TRUE(tracker_.WillPostTask(task.get())); 272 EXPECT_TRUE(tracker_.WillPostTask(task.get()));
234 273
235 // Call Shutdown() asynchronously. 274 // Call Shutdown() asynchronously.
236 CallShutdownAsync(); 275 CallShutdownAsync();
237 EXPECT_EQ(0U, num_tasks_executed_); 276 EXPECT_EQ(0U, NumTasksExecuted());
238 277
239 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { 278 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
240 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); 279 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
241 280
242 // Run the task to unblock shutdown. 281 // Run the task to unblock shutdown.
243 tracker_.RunTask(task.get()); 282 tracker_.RunTask(task.get());
244 EXPECT_EQ(1U, num_tasks_executed_); 283 EXPECT_EQ(1U, NumTasksExecuted());
245 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); 284 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
246 285
247 // It is not possible to test running a BLOCK_SHUTDOWN task posted before 286 // It is not possible to test running a BLOCK_SHUTDOWN task posted before
248 // shutdown after shutdown because Shutdown() won't return if there are 287 // shutdown after shutdown because Shutdown() won't return if there are
249 // pending BLOCK_SHUTDOWN tasks. 288 // pending BLOCK_SHUTDOWN tasks.
250 } else { 289 } else {
251 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); 290 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
252 291
253 // The task shouldn't be allowed to run after shutdown. 292 // The task shouldn't be allowed to run after shutdown.
254 tracker_.RunTask(task.get()); 293 tracker_.RunTask(task.get());
255 EXPECT_EQ(0U, num_tasks_executed_); 294 EXPECT_EQ(0U, NumTasksExecuted());
256 } 295 }
257 } 296 }
258 297
259 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunDuringShutdown) { 298 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunDuringShutdown) {
260 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to 299 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
261 // block shutdown. 300 // block shutdown.
262 std::unique_ptr<Task> block_shutdown_task( 301 std::unique_ptr<Task> block_shutdown_task(
263 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); 302 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
264 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); 303 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get()));
265 304
266 // Call Shutdown() asynchronously. 305 // Call Shutdown() asynchronously.
267 CallShutdownAsync(); 306 CallShutdownAsync();
268 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); 307 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
269 308
270 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { 309 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
271 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted. 310 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted.
272 std::unique_ptr<Task> task(CreateTask(GetParam())); 311 std::unique_ptr<Task> task(CreateTask(GetParam()));
273 EXPECT_TRUE(tracker_.WillPostTask(task.get())); 312 EXPECT_TRUE(tracker_.WillPostTask(task.get()));
274 313
275 // Run the BLOCK_SHUTDOWN task. 314 // Run the BLOCK_SHUTDOWN task.
276 EXPECT_EQ(0U, num_tasks_executed_); 315 EXPECT_EQ(0U, NumTasksExecuted());
277 tracker_.RunTask(task.get()); 316 tracker_.RunTask(task.get());
278 EXPECT_EQ(1U, num_tasks_executed_); 317 EXPECT_EQ(1U, NumTasksExecuted());
279 } else { 318 } else {
280 // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task. 319 // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task.
281 std::unique_ptr<Task> task(CreateTask(GetParam())); 320 std::unique_ptr<Task> task(CreateTask(GetParam()));
282 EXPECT_FALSE(tracker_.WillPostTask(task.get())); 321 EXPECT_FALSE(tracker_.WillPostTask(task.get()));
283 322
284 // Don't try to run the task, because it wasn't allowed to be posted. 323 // Don't try to run the task, because it wasn't allowed to be posted.
285 } 324 }
286 325
287 // Unblock shutdown by running |block_shutdown_task|. 326 // Unblock shutdown by running |block_shutdown_task|.
288 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); 327 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
289 tracker_.RunTask(block_shutdown_task.get()); 328 tracker_.RunTask(block_shutdown_task.get());
290 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, 329 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U,
291 num_tasks_executed_); 330 NumTasksExecuted());
292 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); 331 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
293 } 332 }
294 333
295 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAfterShutdown) { 334 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAfterShutdown) {
296 tracker_.Shutdown(); 335 tracker_.Shutdown();
297 336
298 std::unique_ptr<Task> task(CreateTask(GetParam())); 337 std::unique_ptr<Task> task(CreateTask(GetParam()));
299 338
300 // |task_tracker_| shouldn't allow a task to be posted after shutdown. 339 // |task_tracker_| shouldn't allow a task to be posted after shutdown.
301 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { 340 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 ::testing::Values(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); 454 ::testing::Values(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
416 INSTANTIATE_TEST_CASE_P( 455 INSTANTIATE_TEST_CASE_P(
417 SkipOnShutdown, 456 SkipOnShutdown,
418 TaskSchedulerTaskTrackerTest, 457 TaskSchedulerTaskTrackerTest,
419 ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); 458 ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
420 INSTANTIATE_TEST_CASE_P( 459 INSTANTIATE_TEST_CASE_P(
421 BlockShutdown, 460 BlockShutdown,
422 TaskSchedulerTaskTrackerTest, 461 TaskSchedulerTaskTrackerTest,
423 ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN)); 462 ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN));
424 463
464 TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunBeforeShutdown) {
465 // Post and run tasks asynchronously.
466 std::vector<std::unique_ptr<Task>> tasks;
467 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads;
468
469 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
470 tasks.push_back(CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
471 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
472 &tracker_, tasks.back().get(),
473 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, true)));
474 threads.back()->Start();
475
476 tasks.push_back(CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
477 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
478 &tracker_, tasks.back().get(),
479 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, true)));
480 threads.back()->Start();
481
482 tasks.push_back(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
483 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
484 &tracker_, tasks.back().get(),
485 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, true)));
486 threads.back()->Start();
487 }
488
489 for (const auto& thread : threads)
490 thread->Join();
491
492 // Expect all tasks to be executed.
493 EXPECT_EQ(kLoadTestNumIterations * 3, NumTasksExecuted());
494
495 // Should return immediately because no tasks are blocking shutdown.
496 tracker_.Shutdown();
497 }
498
499 TEST_F(TaskSchedulerTaskTrackerTest,
500 LoadWillPostBeforeShutdownAndRunDuringShutdown) {
501 // Post tasks asynchronously.
502 std::vector<std::unique_ptr<Task>> tasks;
503 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> post_threads;
504
505 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
506 tasks.push_back(CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
507 post_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
508 &tracker_, tasks.back().get(), ThreadPostingAndRunningTask::WILL_POST,
509 true)));
510 post_threads.back()->Start();
511
512 tasks.push_back(CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
513 post_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
514 &tracker_, tasks.back().get(), ThreadPostingAndRunningTask::WILL_POST,
515 true)));
516 post_threads.back()->Start();
517
518 tasks.push_back(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
519 post_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
520 &tracker_, tasks.back().get(), ThreadPostingAndRunningTask::WILL_POST,
521 true)));
522 post_threads.back()->Start();
523 }
524
525 for (const auto& thread : post_threads)
526 thread->Join();
527
528 // Call Shutdown() asynchronously.
529 CallShutdownAsync();
530
531 // Run tasks asynchronously.
532 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> run_threads;
533
534 for (const auto& task : tasks) {
535 run_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
536 &tracker_, task.get(), ThreadPostingAndRunningTask::RUN, false)));
537 run_threads.back()->Start();
538 }
539
540 for (const auto& thread : run_threads)
541 thread->Join();
542
543 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
544
545 // Expect BLOCK_SHUTDOWN tasks to have been executed.
546 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted());
547 }
548
549 TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunDuringShutdown) {
550 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
551 // block shutdown.
552 std::unique_ptr<Task> block_shutdown_task(
553 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
554 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get()));
555
556 // Call Shutdown() asynchronously.
557 CallShutdownAsync();
558
559 // Post and run tasks asynchronously.
560 std::vector<std::unique_ptr<Task>> tasks;
561 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads;
562
563 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
564 tasks.push_back(CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
565 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
566 &tracker_, tasks.back().get(),
567 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, false)));
568 threads.back()->Start();
569
570 tasks.push_back(CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
571 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
572 &tracker_, tasks.back().get(),
573 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, false)));
574 threads.back()->Start();
575
576 tasks.push_back(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
577 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
578 &tracker_, tasks.back().get(),
579 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, true)));
580 threads.back()->Start();
581 }
582
583 for (const auto& thread : threads)
584 thread->Join();
585
586 // Expect BLOCK_SHUTDOWN tasks to have been executed.
587 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted());
588
589 // Shutdown() shouldn't return before |block_shutdown_task| is executed.
590 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
591
592 // Unblock shutdown by running |block_shutdown_task|.
593 tracker_.RunTask(block_shutdown_task.get());
594 EXPECT_EQ(kLoadTestNumIterations + 1, NumTasksExecuted());
595 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
596 }
597
425 } // namespace internal 598 } // namespace internal
426 } // namespace base 599 } // namespace base
OLDNEW
« base/task_scheduler/task_tracker.cc ('K') | « base/task_scheduler/task_tracker.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698