| 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 |