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 <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/macros.h" | 14 #include "base/macros.h" |
15 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
16 #include "base/memory/ref_counted.h" | 16 #include "base/memory/ref_counted.h" |
| 17 #include "base/sequence_token.h" |
17 #include "base/sequenced_task_runner.h" | 18 #include "base/sequenced_task_runner.h" |
18 #include "base/single_thread_task_runner.h" | 19 #include "base/single_thread_task_runner.h" |
19 #include "base/synchronization/waitable_event.h" | 20 #include "base/synchronization/waitable_event.h" |
20 #include "base/task_scheduler/scheduler_lock.h" | 21 #include "base/task_scheduler/scheduler_lock.h" |
| 22 #include "base/task_scheduler/sequence.h" |
21 #include "base/task_scheduler/task.h" | 23 #include "base/task_scheduler/task.h" |
22 #include "base/task_scheduler/task_traits.h" | 24 #include "base/task_scheduler/task_traits.h" |
23 #include "base/task_scheduler/test_utils.h" | 25 #include "base/task_scheduler/test_utils.h" |
24 #include "base/test/test_simple_task_runner.h" | 26 #include "base/test/test_simple_task_runner.h" |
25 #include "base/threading/platform_thread.h" | 27 #include "base/threading/platform_thread.h" |
26 #include "base/threading/sequenced_task_runner_handle.h" | 28 #include "base/threading/sequenced_task_runner_handle.h" |
27 #include "base/threading/simple_thread.h" | 29 #include "base/threading/simple_thread.h" |
28 #include "base/threading/thread_restrictions.h" | 30 #include "base/threading/thread_restrictions.h" |
29 #include "base/threading/thread_task_runner_handle.h" | 31 #include "base/threading/thread_task_runner_handle.h" |
30 #include "testing/gtest/include/gtest/gtest.h" | 32 #include "testing/gtest/include/gtest/gtest.h" |
31 | 33 |
32 namespace base { | 34 namespace base { |
33 namespace internal { | 35 namespace internal { |
34 | 36 |
35 namespace { | 37 namespace { |
36 | 38 |
37 constexpr size_t kLoadTestNumIterations = 100; | 39 constexpr size_t kLoadTestNumIterations = 100; |
38 | 40 |
| 41 scoped_refptr<Sequence> CreateSequenceWithTask(std::unique_ptr<Task> task) { |
| 42 scoped_refptr<Sequence> sequence(new Sequence); |
| 43 sequence->PushTask(std::move(task)); |
| 44 return sequence; |
| 45 } |
| 46 |
39 // Calls TaskTracker::Shutdown() asynchronously. | 47 // Calls TaskTracker::Shutdown() asynchronously. |
40 class ThreadCallingShutdown : public SimpleThread { | 48 class ThreadCallingShutdown : public SimpleThread { |
41 public: | 49 public: |
42 explicit ThreadCallingShutdown(TaskTracker* tracker) | 50 explicit ThreadCallingShutdown(TaskTracker* tracker) |
43 : SimpleThread("ThreadCallingShutdown"), | 51 : SimpleThread("ThreadCallingShutdown"), |
44 tracker_(tracker), | 52 tracker_(tracker), |
45 has_returned_(WaitableEvent::ResetPolicy::MANUAL, | 53 has_returned_(WaitableEvent::ResetPolicy::MANUAL, |
46 WaitableEvent::InitialState::NOT_SIGNALED) {} | 54 WaitableEvent::InitialState::NOT_SIGNALED) {} |
47 | 55 |
48 // Returns true once the async call to Shutdown() has returned. | 56 // Returns true once the async call to Shutdown() has returned. |
(...skipping 13 matching lines...) Expand all Loading... |
62 | 70 |
63 class ThreadPostingAndRunningTask : public SimpleThread { | 71 class ThreadPostingAndRunningTask : public SimpleThread { |
64 public: | 72 public: |
65 enum class Action { | 73 enum class Action { |
66 WILL_POST, | 74 WILL_POST, |
67 RUN, | 75 RUN, |
68 WILL_POST_AND_RUN, | 76 WILL_POST_AND_RUN, |
69 }; | 77 }; |
70 | 78 |
71 ThreadPostingAndRunningTask(TaskTracker* tracker, | 79 ThreadPostingAndRunningTask(TaskTracker* tracker, |
72 const Task* task, | 80 scoped_refptr<Sequence> sequence, |
73 Action action, | 81 Action action, |
74 bool expect_post_succeeds) | 82 bool expect_post_succeeds) |
75 : SimpleThread("ThreadPostingAndRunningTask"), | 83 : SimpleThread("ThreadPostingAndRunningTask"), |
76 tracker_(tracker), | 84 tracker_(tracker), |
77 task_(task), | 85 sequence_(std::move(sequence)), |
78 action_(action), | 86 action_(action), |
79 expect_post_succeeds_(expect_post_succeeds) {} | 87 expect_post_succeeds_(expect_post_succeeds) {} |
80 | 88 |
81 private: | 89 private: |
82 void Run() override { | 90 void Run() override { |
83 bool post_succeeded = true; | 91 bool post_succeeded = true; |
84 if (action_ == Action::WILL_POST || action_ == Action::WILL_POST_AND_RUN) { | 92 if (action_ == Action::WILL_POST || action_ == Action::WILL_POST_AND_RUN) { |
85 post_succeeded = tracker_->WillPostTask(task_); | 93 post_succeeded = tracker_->WillPostTask(sequence_->PeekTask()); |
86 EXPECT_EQ(expect_post_succeeds_, post_succeeded); | 94 EXPECT_EQ(expect_post_succeeds_, post_succeeded); |
87 } | 95 } |
88 if (post_succeeded && | 96 if (post_succeeded && |
89 (action_ == Action::RUN || action_ == Action::WILL_POST_AND_RUN)) { | 97 (action_ == Action::RUN || action_ == Action::WILL_POST_AND_RUN)) { |
90 tracker_->RunTask(task_); | 98 tracker_->RunNextTaskInSequence(sequence_.get()); |
91 } | 99 } |
92 } | 100 } |
93 | 101 |
94 TaskTracker* const tracker_; | 102 TaskTracker* const tracker_; |
95 const Task* const task_; | 103 const scoped_refptr<Sequence> sequence_; |
96 const Action action_; | 104 const Action action_; |
97 const bool expect_post_succeeds_; | 105 const bool expect_post_succeeds_; |
98 | 106 |
99 DISALLOW_COPY_AND_ASSIGN(ThreadPostingAndRunningTask); | 107 DISALLOW_COPY_AND_ASSIGN(ThreadPostingAndRunningTask); |
100 }; | 108 }; |
101 | 109 |
102 class ScopedSetSingletonAllowed { | 110 class ScopedSetSingletonAllowed { |
103 public: | 111 public: |
104 ScopedSetSingletonAllowed(bool singleton_allowed) | 112 ScopedSetSingletonAllowed(bool singleton_allowed) |
105 : previous_value_( | 113 : previous_value_( |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 } // namespace | 196 } // namespace |
189 | 197 |
190 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunBeforeShutdown) { | 198 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunBeforeShutdown) { |
191 std::unique_ptr<Task> task(CreateTask(GetParam())); | 199 std::unique_ptr<Task> task(CreateTask(GetParam())); |
192 | 200 |
193 // Inform |task_tracker_| that |task| will be posted. | 201 // Inform |task_tracker_| that |task| will be posted. |
194 EXPECT_TRUE(tracker_.WillPostTask(task.get())); | 202 EXPECT_TRUE(tracker_.WillPostTask(task.get())); |
195 | 203 |
196 // Run the task. | 204 // Run the task. |
197 EXPECT_EQ(0U, NumTasksExecuted()); | 205 EXPECT_EQ(0U, NumTasksExecuted()); |
198 tracker_.RunTask(task.get()); | 206 tracker_.RunNextTaskInSequence(CreateSequenceWithTask(std::move(task)).get()); |
199 EXPECT_EQ(1U, NumTasksExecuted()); | 207 EXPECT_EQ(1U, NumTasksExecuted()); |
200 | 208 |
201 // Shutdown() shouldn't block. | 209 // Shutdown() shouldn't block. |
202 tracker_.Shutdown(); | 210 tracker_.Shutdown(); |
203 } | 211 } |
204 | 212 |
205 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunLongTaskBeforeShutdown) { | 213 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunLongTaskBeforeShutdown) { |
206 // Create a task that will block until |event| is signaled. | 214 // Create a task that will block until |event| is signaled. |
207 WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC, | 215 WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC, |
208 WaitableEvent::InitialState::NOT_SIGNALED); | 216 WaitableEvent::InitialState::NOT_SIGNALED); |
209 std::unique_ptr<Task> blocked_task( | 217 std::unique_ptr<Task> blocked_task( |
210 new Task(FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&event)), | 218 new Task(FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&event)), |
211 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); | 219 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); |
212 | 220 |
213 // Inform |task_tracker_| that |blocked_task| will be posted. | 221 // Inform |task_tracker_| that |blocked_task| will be posted. |
214 EXPECT_TRUE(tracker_.WillPostTask(blocked_task.get())); | 222 EXPECT_TRUE(tracker_.WillPostTask(blocked_task.get())); |
215 | 223 |
216 // Run the task asynchronouly. | 224 // Run the task asynchronouly. |
217 ThreadPostingAndRunningTask thread_running_task( | 225 ThreadPostingAndRunningTask thread_running_task( |
218 &tracker_, blocked_task.get(), ThreadPostingAndRunningTask::Action::RUN, | 226 &tracker_, CreateSequenceWithTask(std::move(blocked_task)), |
219 false); | 227 ThreadPostingAndRunningTask::Action::RUN, false); |
220 thread_running_task.Start(); | 228 thread_running_task.Start(); |
221 | 229 |
222 // Initiate shutdown while the task is running. | 230 // Initiate shutdown while the task is running. |
223 CallShutdownAsync(); | 231 CallShutdownAsync(); |
224 | 232 |
225 if (GetParam() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) { | 233 if (GetParam() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) { |
226 // Shutdown should complete even with a CONTINUE_ON_SHUTDOWN in progress. | 234 // Shutdown should complete even with a CONTINUE_ON_SHUTDOWN in progress. |
227 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | 235 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
228 } else { | 236 } else { |
229 // Shutdown should block with any non CONTINUE_ON_SHUTDOWN task in progress. | 237 // Shutdown should block with any non CONTINUE_ON_SHUTDOWN task in progress. |
(...skipping 20 matching lines...) Expand all Loading... |
250 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 258 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
251 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); | 259 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); |
252 | 260 |
253 // Call Shutdown() asynchronously. | 261 // Call Shutdown() asynchronously. |
254 CallShutdownAsync(); | 262 CallShutdownAsync(); |
255 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); | 263 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
256 | 264 |
257 // Try to run |task|. It should only run it it's BLOCK_SHUTDOWN. Otherwise it | 265 // Try to run |task|. It should only run it it's BLOCK_SHUTDOWN. Otherwise it |
258 // should be discarded. | 266 // should be discarded. |
259 EXPECT_EQ(0U, NumTasksExecuted()); | 267 EXPECT_EQ(0U, NumTasksExecuted()); |
260 tracker_.RunTask(task.get()); | 268 tracker_.RunNextTaskInSequence(CreateSequenceWithTask(std::move(task)).get()); |
261 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 1U : 0U, | 269 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 1U : 0U, |
262 NumTasksExecuted()); | 270 NumTasksExecuted()); |
263 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); | 271 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
264 | 272 |
265 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task. | 273 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task. |
266 tracker_.RunTask(block_shutdown_task.get()); | 274 tracker_.RunNextTaskInSequence( |
| 275 CreateSequenceWithTask(std::move(block_shutdown_task)).get()); |
267 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, | 276 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, |
268 NumTasksExecuted()); | 277 NumTasksExecuted()); |
269 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | 278 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
270 } | 279 } |
271 | 280 |
272 TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) { | 281 TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) { |
273 // Inform |task_tracker_| that a task will be posted. | 282 // Inform |task_tracker_| that a task will be posted. |
274 std::unique_ptr<Task> task(CreateTask(GetParam())); | 283 std::unique_ptr<Task> task(CreateTask(GetParam())); |
275 EXPECT_TRUE(tracker_.WillPostTask(task.get())); | 284 EXPECT_TRUE(tracker_.WillPostTask(task.get())); |
276 | 285 |
277 // Call Shutdown() asynchronously. | 286 // Call Shutdown() asynchronously. |
278 CallShutdownAsync(); | 287 CallShutdownAsync(); |
279 EXPECT_EQ(0U, NumTasksExecuted()); | 288 EXPECT_EQ(0U, NumTasksExecuted()); |
280 | 289 |
281 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { | 290 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { |
282 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); | 291 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
283 | 292 |
284 // Run the task to unblock shutdown. | 293 // Run the task to unblock shutdown. |
285 tracker_.RunTask(task.get()); | 294 tracker_.RunNextTaskInSequence( |
| 295 CreateSequenceWithTask(std::move(task)).get()); |
286 EXPECT_EQ(1U, NumTasksExecuted()); | 296 EXPECT_EQ(1U, NumTasksExecuted()); |
287 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | 297 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
288 | 298 |
289 // It is not possible to test running a BLOCK_SHUTDOWN task posted before | 299 // It is not possible to test running a BLOCK_SHUTDOWN task posted before |
290 // shutdown after shutdown because Shutdown() won't return if there are | 300 // shutdown after shutdown because Shutdown() won't return if there are |
291 // pending BLOCK_SHUTDOWN tasks. | 301 // pending BLOCK_SHUTDOWN tasks. |
292 } else { | 302 } else { |
293 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | 303 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
294 | 304 |
295 // The task shouldn't be allowed to run after shutdown. | 305 // The task shouldn't be allowed to run after shutdown. |
296 tracker_.RunTask(task.get()); | 306 tracker_.RunNextTaskInSequence( |
| 307 CreateSequenceWithTask(std::move(task)).get()); |
297 EXPECT_EQ(0U, NumTasksExecuted()); | 308 EXPECT_EQ(0U, NumTasksExecuted()); |
298 } | 309 } |
299 } | 310 } |
300 | 311 |
301 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunDuringShutdown) { | 312 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunDuringShutdown) { |
302 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to | 313 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to |
303 // block shutdown. | 314 // block shutdown. |
304 std::unique_ptr<Task> block_shutdown_task( | 315 std::unique_ptr<Task> block_shutdown_task( |
305 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 316 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
306 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); | 317 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); |
307 | 318 |
308 // Call Shutdown() asynchronously. | 319 // Call Shutdown() asynchronously. |
309 CallShutdownAsync(); | 320 CallShutdownAsync(); |
310 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); | 321 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
311 | 322 |
312 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { | 323 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { |
313 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted. | 324 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted. |
314 std::unique_ptr<Task> task(CreateTask(GetParam())); | 325 std::unique_ptr<Task> task(CreateTask(GetParam())); |
315 EXPECT_TRUE(tracker_.WillPostTask(task.get())); | 326 EXPECT_TRUE(tracker_.WillPostTask(task.get())); |
316 | 327 |
317 // Run the BLOCK_SHUTDOWN task. | 328 // Run the BLOCK_SHUTDOWN task. |
318 EXPECT_EQ(0U, NumTasksExecuted()); | 329 EXPECT_EQ(0U, NumTasksExecuted()); |
319 tracker_.RunTask(task.get()); | 330 tracker_.RunNextTaskInSequence( |
| 331 CreateSequenceWithTask(std::move(task)).get()); |
320 EXPECT_EQ(1U, NumTasksExecuted()); | 332 EXPECT_EQ(1U, NumTasksExecuted()); |
321 } else { | 333 } else { |
322 // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task. | 334 // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task. |
323 std::unique_ptr<Task> task(CreateTask(GetParam())); | 335 std::unique_ptr<Task> task(CreateTask(GetParam())); |
324 EXPECT_FALSE(tracker_.WillPostTask(task.get())); | 336 EXPECT_FALSE(tracker_.WillPostTask(task.get())); |
325 | 337 |
326 // Don't try to run the task, because it wasn't allowed to be posted. | 338 // Don't try to run the task, because it wasn't allowed to be posted. |
327 } | 339 } |
328 | 340 |
329 // Unblock shutdown by running |block_shutdown_task|. | 341 // Unblock shutdown by running |block_shutdown_task|. |
330 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); | 342 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
331 tracker_.RunTask(block_shutdown_task.get()); | 343 tracker_.RunNextTaskInSequence( |
| 344 CreateSequenceWithTask(std::move(block_shutdown_task)).get()); |
332 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, | 345 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, |
333 NumTasksExecuted()); | 346 NumTasksExecuted()); |
334 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | 347 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
335 } | 348 } |
336 | 349 |
337 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAfterShutdown) { | 350 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAfterShutdown) { |
338 tracker_.Shutdown(); | 351 tracker_.Shutdown(); |
339 | 352 |
340 std::unique_ptr<Task> task(CreateTask(GetParam())); | 353 std::unique_ptr<Task> task(CreateTask(GetParam())); |
341 | 354 |
342 // |task_tracker_| shouldn't allow a task to be posted after shutdown. | 355 // |task_tracker_| shouldn't allow a task to be posted after shutdown. |
343 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { | 356 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { |
344 EXPECT_DCHECK_DEATH({ tracker_.WillPostTask(task.get()); }, ""); | 357 EXPECT_DCHECK_DEATH({ tracker_.WillPostTask(task.get()); }, ""); |
345 } else { | 358 } else { |
346 EXPECT_FALSE(tracker_.WillPostTask(task.get())); | 359 EXPECT_FALSE(tracker_.WillPostTask(task.get())); |
347 } | 360 } |
348 } | 361 } |
349 | 362 |
350 // Verify that BLOCK_SHUTDOWN and SKIP_ON_SHUTDOWN tasks can | 363 // Verify that BLOCK_SHUTDOWN and SKIP_ON_SHUTDOWN tasks can |
351 // AssertSingletonAllowed() but CONTINUE_ON_SHUTDOWN tasks can't. | 364 // AssertSingletonAllowed() but CONTINUE_ON_SHUTDOWN tasks can't. |
352 TEST_P(TaskSchedulerTaskTrackerTest, SingletonAllowed) { | 365 TEST_P(TaskSchedulerTaskTrackerTest, SingletonAllowed) { |
353 const bool can_use_singletons = | 366 const bool can_use_singletons = |
354 (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN); | 367 (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN); |
355 | 368 |
356 TaskTracker tracker; | 369 TaskTracker tracker; |
357 Task task(FROM_HERE, Bind(&ThreadRestrictions::AssertSingletonAllowed), | 370 std::unique_ptr<Task> task( |
358 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()); | 371 new Task(FROM_HERE, Bind(&ThreadRestrictions::AssertSingletonAllowed), |
359 EXPECT_TRUE(tracker.WillPostTask(&task)); | 372 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); |
| 373 EXPECT_TRUE(tracker.WillPostTask(task.get())); |
360 | 374 |
361 // Set the singleton allowed bit to the opposite of what it is expected to be | 375 // Set the singleton allowed bit to the opposite of what it is expected to be |
362 // when |tracker| runs |task| to verify that |tracker| actually sets the | 376 // when |tracker| runs |task| to verify that |tracker| actually sets the |
363 // correct value. | 377 // correct value. |
364 ScopedSetSingletonAllowed scoped_singleton_allowed(!can_use_singletons); | 378 ScopedSetSingletonAllowed scoped_singleton_allowed(!can_use_singletons); |
365 | 379 |
366 // Running the task should fail iff the task isn't allowed to use singletons. | 380 // Running the task should fail iff the task isn't allowed to use singletons. |
367 if (can_use_singletons) { | 381 if (can_use_singletons) { |
368 tracker.RunTask(&task); | 382 tracker.RunNextTaskInSequence( |
| 383 CreateSequenceWithTask(std::move(task)).get()); |
369 } else { | 384 } else { |
370 EXPECT_DCHECK_DEATH({ tracker.RunTask(&task); }, ""); | 385 EXPECT_DCHECK_DEATH( |
| 386 { |
| 387 tracker.RunNextTaskInSequence( |
| 388 CreateSequenceWithTask(std::move(task)).get()); |
| 389 }, |
| 390 ""); |
371 } | 391 } |
372 } | 392 } |
373 | 393 |
374 static void RunTaskRunnerHandleVerificationTask(TaskTracker* tracker, | 394 static void RunTaskRunnerHandleVerificationTask( |
375 const Task* verify_task) { | 395 TaskTracker* tracker, |
| 396 std::unique_ptr<Task> verify_task) { |
376 // Pretend |verify_task| is posted to respect TaskTracker's contract. | 397 // Pretend |verify_task| is posted to respect TaskTracker's contract. |
377 EXPECT_TRUE(tracker->WillPostTask(verify_task)); | 398 EXPECT_TRUE(tracker->WillPostTask(verify_task.get())); |
378 | 399 |
379 // Confirm that the test conditions are right (no TaskRunnerHandles set | 400 // Confirm that the test conditions are right (no TaskRunnerHandles set |
380 // already). | 401 // already). |
381 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); | 402 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); |
382 EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet()); | 403 EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet()); |
383 | 404 |
384 tracker->RunTask(verify_task); | 405 tracker->RunNextTaskInSequence( |
| 406 CreateSequenceWithTask(std::move(verify_task)).get()); |
385 | 407 |
386 // TaskRunnerHandle state is reset outside of task's scope. | 408 // TaskRunnerHandle state is reset outside of task's scope. |
387 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); | 409 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); |
388 EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet()); | 410 EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet()); |
389 } | 411 } |
390 | 412 |
391 static void VerifyNoTaskRunnerHandle() { | 413 static void VerifyNoTaskRunnerHandle() { |
392 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); | 414 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); |
393 EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet()); | 415 EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet()); |
394 } | 416 } |
395 | 417 |
396 TEST_P(TaskSchedulerTaskTrackerTest, TaskRunnerHandleIsNotSetOnParallel) { | 418 TEST_P(TaskSchedulerTaskTrackerTest, TaskRunnerHandleIsNotSetOnParallel) { |
397 // Create a task that will verify that TaskRunnerHandles are not set in its | 419 // Create a task that will verify that TaskRunnerHandles are not set in its |
398 // scope per no TaskRunner ref being set to it. | 420 // scope per no TaskRunner ref being set to it. |
399 std::unique_ptr<Task> verify_task( | 421 std::unique_ptr<Task> verify_task( |
400 new Task(FROM_HERE, Bind(&VerifyNoTaskRunnerHandle), | 422 new Task(FROM_HERE, Bind(&VerifyNoTaskRunnerHandle), |
401 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); | 423 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); |
402 | 424 |
403 RunTaskRunnerHandleVerificationTask(&tracker_, verify_task.get()); | 425 RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task)); |
404 } | 426 } |
405 | 427 |
406 static void VerifySequencedTaskRunnerHandle( | 428 static void VerifySequencedTaskRunnerHandle( |
407 const SequencedTaskRunner* expected_task_runner) { | 429 const SequencedTaskRunner* expected_task_runner) { |
408 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); | 430 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); |
409 EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet()); | 431 EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet()); |
410 EXPECT_EQ(expected_task_runner, SequencedTaskRunnerHandle::Get()); | 432 EXPECT_EQ(expected_task_runner, SequencedTaskRunnerHandle::Get()); |
411 } | 433 } |
412 | 434 |
413 TEST_P(TaskSchedulerTaskTrackerTest, | 435 TEST_P(TaskSchedulerTaskTrackerTest, |
414 SequencedTaskRunnerHandleIsSetOnSequenced) { | 436 SequencedTaskRunnerHandleIsSetOnSequenced) { |
415 scoped_refptr<SequencedTaskRunner> test_task_runner(new TestSimpleTaskRunner); | 437 scoped_refptr<SequencedTaskRunner> test_task_runner(new TestSimpleTaskRunner); |
416 | 438 |
417 // Create a task that will verify that SequencedTaskRunnerHandle is properly | 439 // Create a task that will verify that SequencedTaskRunnerHandle is properly |
418 // set to |test_task_runner| in its scope per |sequenced_task_runner_ref| | 440 // set to |test_task_runner| in its scope per |sequenced_task_runner_ref| |
419 // being set to it. | 441 // being set to it. |
420 std::unique_ptr<Task> verify_task( | 442 std::unique_ptr<Task> verify_task( |
421 new Task(FROM_HERE, Bind(&VerifySequencedTaskRunnerHandle, | 443 new Task(FROM_HERE, Bind(&VerifySequencedTaskRunnerHandle, |
422 base::Unretained(test_task_runner.get())), | 444 base::Unretained(test_task_runner.get())), |
423 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); | 445 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); |
424 verify_task->sequenced_task_runner_ref = test_task_runner; | 446 verify_task->sequenced_task_runner_ref = test_task_runner; |
425 | 447 |
426 RunTaskRunnerHandleVerificationTask(&tracker_, verify_task.get()); | 448 RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task)); |
427 } | 449 } |
428 | 450 |
429 static void VerifyThreadTaskRunnerHandle( | 451 static void VerifyThreadTaskRunnerHandle( |
430 const SingleThreadTaskRunner* expected_task_runner) { | 452 const SingleThreadTaskRunner* expected_task_runner) { |
431 EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet()); | 453 EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet()); |
432 // SequencedTaskRunnerHandle inherits ThreadTaskRunnerHandle for thread. | 454 // SequencedTaskRunnerHandle inherits ThreadTaskRunnerHandle for thread. |
433 EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet()); | 455 EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet()); |
434 EXPECT_EQ(expected_task_runner, ThreadTaskRunnerHandle::Get()); | 456 EXPECT_EQ(expected_task_runner, ThreadTaskRunnerHandle::Get()); |
435 } | 457 } |
436 | 458 |
437 TEST_P(TaskSchedulerTaskTrackerTest, | 459 TEST_P(TaskSchedulerTaskTrackerTest, |
438 ThreadTaskRunnerHandleIsSetOnSingleThreaded) { | 460 ThreadTaskRunnerHandleIsSetOnSingleThreaded) { |
439 scoped_refptr<SingleThreadTaskRunner> test_task_runner( | 461 scoped_refptr<SingleThreadTaskRunner> test_task_runner( |
440 new TestSimpleTaskRunner); | 462 new TestSimpleTaskRunner); |
441 | 463 |
442 // Create a task that will verify that ThreadTaskRunnerHandle is properly set | 464 // Create a task that will verify that ThreadTaskRunnerHandle is properly set |
443 // to |test_task_runner| in its scope per |single_thread_task_runner_ref| | 465 // to |test_task_runner| in its scope per |single_thread_task_runner_ref| |
444 // being set on it. | 466 // being set on it. |
445 std::unique_ptr<Task> verify_task( | 467 std::unique_ptr<Task> verify_task( |
446 new Task(FROM_HERE, Bind(&VerifyThreadTaskRunnerHandle, | 468 new Task(FROM_HERE, Bind(&VerifyThreadTaskRunnerHandle, |
447 base::Unretained(test_task_runner.get())), | 469 base::Unretained(test_task_runner.get())), |
448 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); | 470 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); |
449 verify_task->single_thread_task_runner_ref = test_task_runner; | 471 verify_task->single_thread_task_runner_ref = test_task_runner; |
450 | 472 |
451 RunTaskRunnerHandleVerificationTask(&tracker_, verify_task.get()); | 473 RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task)); |
452 } | 474 } |
453 | 475 |
454 INSTANTIATE_TEST_CASE_P( | 476 INSTANTIATE_TEST_CASE_P( |
455 ContinueOnShutdown, | 477 ContinueOnShutdown, |
456 TaskSchedulerTaskTrackerTest, | 478 TaskSchedulerTaskTrackerTest, |
457 ::testing::Values(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); | 479 ::testing::Values(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); |
458 INSTANTIATE_TEST_CASE_P( | 480 INSTANTIATE_TEST_CASE_P( |
459 SkipOnShutdown, | 481 SkipOnShutdown, |
460 TaskSchedulerTaskTrackerTest, | 482 TaskSchedulerTaskTrackerTest, |
461 ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); | 483 ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); |
462 INSTANTIATE_TEST_CASE_P( | 484 INSTANTIATE_TEST_CASE_P( |
463 BlockShutdown, | 485 BlockShutdown, |
464 TaskSchedulerTaskTrackerTest, | 486 TaskSchedulerTaskTrackerTest, |
465 ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 487 ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
466 | 488 |
| 489 namespace { |
| 490 |
| 491 void ExpectSequenceToken(SequenceToken sequence_token) { |
| 492 EXPECT_EQ(sequence_token, SequenceToken::GetForCurrentThread()); |
| 493 } |
| 494 |
| 495 } // namespace |
| 496 |
| 497 // Verify that SequenceToken::GetForCurrentThread() returns the Sequence's token |
| 498 // when a Task runs. |
| 499 TEST_F(TaskSchedulerTaskTrackerTest, CurrentSequenceToken) { |
| 500 scoped_refptr<Sequence> sequence(new Sequence); |
| 501 sequence->PushTask(WrapUnique( |
| 502 new Task(FROM_HERE, Bind(&ExpectSequenceToken, sequence->token()), |
| 503 TaskTraits(), TimeDelta()))); |
| 504 tracker_.WillPostTask(sequence->PeekTask()); |
| 505 |
| 506 EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid()); |
| 507 tracker_.RunNextTaskInSequence(sequence.get()); |
| 508 EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid()); |
| 509 } |
| 510 |
467 TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunBeforeShutdown) { | 511 TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunBeforeShutdown) { |
468 // Post and run tasks asynchronously. | 512 // Post and run tasks asynchronously. |
469 std::vector<std::unique_ptr<Task>> tasks; | |
470 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads; | 513 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads; |
471 | 514 |
472 for (size_t i = 0; i < kLoadTestNumIterations; ++i) { | 515 for (size_t i = 0; i < kLoadTestNumIterations; ++i) { |
473 tasks.push_back(CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); | |
474 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | 516 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( |
475 &tracker_, tasks.back().get(), | 517 &tracker_, CreateSequenceWithTask( |
| 518 CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)), |
476 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true))); | 519 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true))); |
477 threads.back()->Start(); | 520 threads.back()->Start(); |
478 | 521 |
479 tasks.push_back(CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); | |
480 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | 522 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( |
481 &tracker_, tasks.back().get(), | 523 &tracker_, CreateSequenceWithTask( |
| 524 CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)), |
482 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true))); | 525 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true))); |
483 threads.back()->Start(); | 526 threads.back()->Start(); |
484 | 527 |
485 tasks.push_back(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | |
486 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | 528 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( |
487 &tracker_, tasks.back().get(), | 529 &tracker_, CreateSequenceWithTask( |
| 530 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)), |
488 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true))); | 531 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true))); |
489 threads.back()->Start(); | 532 threads.back()->Start(); |
490 } | 533 } |
491 | 534 |
492 for (const auto& thread : threads) | 535 for (const auto& thread : threads) |
493 thread->Join(); | 536 thread->Join(); |
494 | 537 |
495 // Expect all tasks to be executed. | 538 // Expect all tasks to be executed. |
496 EXPECT_EQ(kLoadTestNumIterations * 3, NumTasksExecuted()); | 539 EXPECT_EQ(kLoadTestNumIterations * 3, NumTasksExecuted()); |
497 | 540 |
498 // Should return immediately because no tasks are blocking shutdown. | 541 // Should return immediately because no tasks are blocking shutdown. |
499 tracker_.Shutdown(); | 542 tracker_.Shutdown(); |
500 } | 543 } |
501 | 544 |
502 TEST_F(TaskSchedulerTaskTrackerTest, | 545 TEST_F(TaskSchedulerTaskTrackerTest, |
503 LoadWillPostBeforeShutdownAndRunDuringShutdown) { | 546 LoadWillPostBeforeShutdownAndRunDuringShutdown) { |
504 // Post tasks asynchronously. | 547 // Post tasks asynchronously. |
505 std::vector<std::unique_ptr<Task>> tasks; | 548 std::vector<scoped_refptr<Sequence>> sequences; |
506 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> post_threads; | 549 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> post_threads; |
507 | 550 |
508 for (size_t i = 0; i < kLoadTestNumIterations; ++i) { | 551 for (size_t i = 0; i < kLoadTestNumIterations; ++i) { |
509 tasks.push_back(CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); | 552 sequences.push_back(CreateSequenceWithTask( |
| 553 CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN))); |
510 post_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | 554 post_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( |
511 &tracker_, tasks.back().get(), | 555 &tracker_, sequences.back(), |
512 ThreadPostingAndRunningTask::Action::WILL_POST, true))); | 556 ThreadPostingAndRunningTask::Action::WILL_POST, true))); |
513 post_threads.back()->Start(); | 557 post_threads.back()->Start(); |
514 | 558 |
515 tasks.push_back(CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); | 559 sequences.push_back(CreateSequenceWithTask( |
| 560 CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN))); |
516 post_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | 561 post_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( |
517 &tracker_, tasks.back().get(), | 562 &tracker_, sequences.back(), |
518 ThreadPostingAndRunningTask::Action::WILL_POST, true))); | 563 ThreadPostingAndRunningTask::Action::WILL_POST, true))); |
519 post_threads.back()->Start(); | 564 post_threads.back()->Start(); |
520 | 565 |
521 tasks.push_back(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 566 sequences.push_back(CreateSequenceWithTask( |
| 567 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN))); |
522 post_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | 568 post_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( |
523 &tracker_, tasks.back().get(), | 569 &tracker_, sequences.back(), |
524 ThreadPostingAndRunningTask::Action::WILL_POST, true))); | 570 ThreadPostingAndRunningTask::Action::WILL_POST, true))); |
525 post_threads.back()->Start(); | 571 post_threads.back()->Start(); |
526 } | 572 } |
527 | 573 |
528 for (const auto& thread : post_threads) | 574 for (const auto& thread : post_threads) |
529 thread->Join(); | 575 thread->Join(); |
530 | 576 |
531 // Call Shutdown() asynchronously. | 577 // Call Shutdown() asynchronously. |
532 CallShutdownAsync(); | 578 CallShutdownAsync(); |
533 | 579 |
534 // Run tasks asynchronously. | 580 // Run tasks asynchronously. |
535 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> run_threads; | 581 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> run_threads; |
536 | 582 |
537 for (const auto& task : tasks) { | 583 for (const auto& sequence : sequences) { |
538 run_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | 584 run_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( |
539 &tracker_, task.get(), ThreadPostingAndRunningTask::Action::RUN, | 585 &tracker_, sequence, ThreadPostingAndRunningTask::Action::RUN, false))); |
540 false))); | |
541 run_threads.back()->Start(); | 586 run_threads.back()->Start(); |
542 } | 587 } |
543 | 588 |
544 for (const auto& thread : run_threads) | 589 for (const auto& thread : run_threads) |
545 thread->Join(); | 590 thread->Join(); |
546 | 591 |
547 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | 592 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
548 | 593 |
549 // Expect BLOCK_SHUTDOWN tasks to have been executed. | 594 // Expect BLOCK_SHUTDOWN tasks to have been executed. |
550 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted()); | 595 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted()); |
551 } | 596 } |
552 | 597 |
553 TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunDuringShutdown) { | 598 TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunDuringShutdown) { |
554 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to | 599 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to |
555 // block shutdown. | 600 // block shutdown. |
556 std::unique_ptr<Task> block_shutdown_task( | 601 std::unique_ptr<Task> block_shutdown_task( |
557 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 602 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
558 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); | 603 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); |
559 | 604 |
560 // Call Shutdown() asynchronously. | 605 // Call Shutdown() asynchronously. |
561 CallShutdownAsync(); | 606 CallShutdownAsync(); |
562 | 607 |
563 // Post and run tasks asynchronously. | 608 // Post and run tasks asynchronously. |
564 std::vector<std::unique_ptr<Task>> tasks; | |
565 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads; | 609 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads; |
566 | 610 |
567 for (size_t i = 0; i < kLoadTestNumIterations; ++i) { | 611 for (size_t i = 0; i < kLoadTestNumIterations; ++i) { |
568 tasks.push_back(CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); | |
569 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | 612 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( |
570 &tracker_, tasks.back().get(), | 613 &tracker_, CreateSequenceWithTask( |
| 614 CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)), |
571 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false))); | 615 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false))); |
572 threads.back()->Start(); | 616 threads.back()->Start(); |
573 | 617 |
574 tasks.push_back(CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); | |
575 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | 618 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( |
576 &tracker_, tasks.back().get(), | 619 &tracker_, CreateSequenceWithTask( |
| 620 CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)), |
577 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false))); | 621 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false))); |
578 threads.back()->Start(); | 622 threads.back()->Start(); |
579 | 623 |
580 tasks.push_back(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | |
581 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | 624 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( |
582 &tracker_, tasks.back().get(), | 625 &tracker_, CreateSequenceWithTask( |
| 626 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)), |
583 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true))); | 627 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true))); |
584 threads.back()->Start(); | 628 threads.back()->Start(); |
585 } | 629 } |
586 | 630 |
587 for (const auto& thread : threads) | 631 for (const auto& thread : threads) |
588 thread->Join(); | 632 thread->Join(); |
589 | 633 |
590 // Expect BLOCK_SHUTDOWN tasks to have been executed. | 634 // Expect BLOCK_SHUTDOWN tasks to have been executed. |
591 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted()); | 635 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted()); |
592 | 636 |
593 // Shutdown() shouldn't return before |block_shutdown_task| is executed. | 637 // Shutdown() shouldn't return before |block_shutdown_task| is executed. |
594 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); | 638 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
595 | 639 |
596 // Unblock shutdown by running |block_shutdown_task|. | 640 // Unblock shutdown by running |block_shutdown_task|. |
597 tracker_.RunTask(block_shutdown_task.get()); | 641 tracker_.RunNextTaskInSequence( |
| 642 CreateSequenceWithTask(std::move(block_shutdown_task)).get()); |
598 EXPECT_EQ(kLoadTestNumIterations + 1, NumTasksExecuted()); | 643 EXPECT_EQ(kLoadTestNumIterations + 1, NumTasksExecuted()); |
599 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | 644 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
600 } | 645 } |
601 | 646 |
602 } // namespace internal | 647 } // namespace internal |
603 } // namespace base | 648 } // namespace base |
OLD | NEW |