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

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