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