[email protected] | 5761ab9c | 2012-02-04 16:44:53 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 89993aee | 2012-04-11 08:10:11 | [diff] [blame] | 5 | #include "base/threading/sequenced_worker_pool.h" |
| 6 | |
avi | 9ceb8b8 | 2015-12-24 21:53:59 | [diff] [blame] | 7 | #include <stddef.h> |
| 8 | |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 9 | #include <algorithm> |
dcheng | 093de9b | 2016-04-04 21:25:51 | [diff] [blame] | 10 | #include <memory> |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 11 | |
| 12 | #include "base/bind.h" |
[email protected] | 71b18fb | 2012-03-06 14:17:34 | [diff] [blame] | 13 | #include "base/compiler_specific.h" |
avi | 9ceb8b8 | 2015-12-24 21:53:59 | [diff] [blame] | 14 | #include "base/macros.h" |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 15 | #include "base/memory/ref_counted.h" |
[email protected] | 495cad9 | 2013-07-18 08:12:40 | [diff] [blame] | 16 | #include "base/message_loop/message_loop.h" |
thestig | 6c335d4 | 2015-12-07 18:25:34 | [diff] [blame] | 17 | #include "base/stl_util.h" |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 18 | #include "base/synchronization/condition_variable.h" |
| 19 | #include "base/synchronization/lock.h" |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 20 | #include "base/task_scheduler/scheduler_worker_pool_params.h" |
| 21 | #include "base/task_scheduler/task_scheduler.h" |
[email protected] | 89993aee | 2012-04-11 08:10:11 | [diff] [blame] | 22 | #include "base/test/sequenced_task_runner_test_template.h" |
[email protected] | 8f9a3a5 | 2013-06-28 15:14:18 | [diff] [blame] | 23 | #include "base/test/sequenced_worker_pool_owner.h" |
[email protected] | c8cae7c | 2012-03-09 06:20:18 | [diff] [blame] | 24 | #include "base/test/task_runner_test_template.h" |
[email protected] | 4402478 | 2013-02-26 22:59:50 | [diff] [blame] | 25 | #include "base/test/test_timeouts.h" |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 26 | #include "base/threading/platform_thread.h" |
[email protected] | 8f9a3a5 | 2013-06-28 15:14:18 | [diff] [blame] | 27 | #include "base/time/time.h" |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 28 | #include "testing/gtest/include/gtest/gtest.h" |
| 29 | |
| 30 | namespace base { |
| 31 | |
| 32 | // IMPORTANT NOTE: |
| 33 | // |
| 34 | // Many of these tests have failure modes where they'll hang forever. These |
[email protected] | 4f60d80 | 2013-04-18 05:41:23 | [diff] [blame] | 35 | // tests should not be flaky, and hanging indicates a type of failure. Do not |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 36 | // mark as flaky if they're hanging, it's likely an actual bug. |
| 37 | |
| 38 | namespace { |
| 39 | |
| 40 | const size_t kNumWorkerThreads = 3; |
| 41 | |
| 42 | // Allows a number of threads to all be blocked on the same event, and |
| 43 | // provides a way to unblock a certain number of them. |
| 44 | class ThreadBlocker { |
| 45 | public: |
[email protected] | a9aaa9d1 | 2012-04-25 00:42:51 | [diff] [blame] | 46 | ThreadBlocker() : lock_(), cond_var_(&lock_), unblock_counter_(0) {} |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 47 | |
| 48 | void Block() { |
| 49 | { |
| 50 | base::AutoLock lock(lock_); |
| 51 | while (unblock_counter_ == 0) |
| 52 | cond_var_.Wait(); |
| 53 | unblock_counter_--; |
| 54 | } |
| 55 | cond_var_.Signal(); |
| 56 | } |
| 57 | |
| 58 | void Unblock(size_t count) { |
| 59 | { |
| 60 | base::AutoLock lock(lock_); |
danakj | 94219a21 | 2015-03-09 22:27:25 | [diff] [blame] | 61 | DCHECK_EQ(unblock_counter_, 0u); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 62 | unblock_counter_ = count; |
| 63 | } |
| 64 | cond_var_.Signal(); |
| 65 | } |
| 66 | |
| 67 | private: |
| 68 | base::Lock lock_; |
| 69 | base::ConditionVariable cond_var_; |
| 70 | |
| 71 | size_t unblock_counter_; |
| 72 | }; |
| 73 | |
erikchen | eae82f2 | 2015-02-26 19:37:42 | [diff] [blame] | 74 | class DestructionDeadlockChecker |
| 75 | : public base::RefCountedThreadSafe<DestructionDeadlockChecker> { |
| 76 | public: |
vmpstr | 82b0c16d | 2016-03-18 19:17:28 | [diff] [blame] | 77 | explicit DestructionDeadlockChecker(scoped_refptr<SequencedWorkerPool> pool) |
| 78 | : pool_(std::move(pool)) {} |
erikchen | eae82f2 | 2015-02-26 19:37:42 | [diff] [blame] | 79 | |
| 80 | protected: |
| 81 | virtual ~DestructionDeadlockChecker() { |
| 82 | // This method should not deadlock. |
Yeol | a89b266 | 2017-07-25 17:09:10 | [diff] [blame] | 83 | pool_->RunsTasksInCurrentSequence(); |
erikchen | eae82f2 | 2015-02-26 19:37:42 | [diff] [blame] | 84 | } |
| 85 | |
| 86 | private: |
| 87 | scoped_refptr<SequencedWorkerPool> pool_; |
| 88 | friend class base::RefCountedThreadSafe<DestructionDeadlockChecker>; |
| 89 | }; |
| 90 | |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 91 | class TestTracker : public base::RefCountedThreadSafe<TestTracker> { |
| 92 | public: |
| 93 | TestTracker() |
| 94 | : lock_(), |
| 95 | cond_var_(&lock_), |
| 96 | started_events_(0) { |
| 97 | } |
| 98 | |
| 99 | // Each of these tasks appends the argument to the complete sequence vector |
| 100 | // so calling code can see what order they finished in. |
| 101 | void FastTask(int id) { |
| 102 | SignalWorkerDone(id); |
| 103 | } |
[email protected] | a9aaa9d1 | 2012-04-25 00:42:51 | [diff] [blame] | 104 | |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 105 | void SlowTask(int id) { |
[email protected] | 5761ab9c | 2012-02-04 16:44:53 | [diff] [blame] | 106 | base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1)); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 107 | SignalWorkerDone(id); |
| 108 | } |
| 109 | |
| 110 | void BlockTask(int id, ThreadBlocker* blocker) { |
| 111 | // Note that this task has started and signal anybody waiting for that |
| 112 | // to happen. |
| 113 | { |
| 114 | base::AutoLock lock(lock_); |
| 115 | started_events_++; |
| 116 | } |
| 117 | cond_var_.Signal(); |
| 118 | |
| 119 | blocker->Block(); |
| 120 | SignalWorkerDone(id); |
| 121 | } |
| 122 | |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 123 | void PostAdditionalTasks( |
| 124 | int id, SequencedWorkerPool* pool, |
| 125 | bool expected_return_value) { |
[email protected] | 270f2cf | 2012-12-19 01:56:37 | [diff] [blame] | 126 | Closure fast_task = base::Bind(&TestTracker::FastTask, this, 100); |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 127 | EXPECT_EQ(expected_return_value, |
| 128 | pool->PostWorkerTaskWithShutdownBehavior( |
| 129 | FROM_HERE, fast_task, |
| 130 | SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); |
| 131 | EXPECT_EQ(expected_return_value, |
| 132 | pool->PostWorkerTaskWithShutdownBehavior( |
| 133 | FROM_HERE, fast_task, |
| 134 | SequencedWorkerPool::SKIP_ON_SHUTDOWN)); |
[email protected] | 270f2cf | 2012-12-19 01:56:37 | [diff] [blame] | 135 | pool->PostWorkerTaskWithShutdownBehavior( |
| 136 | FROM_HERE, fast_task, |
| 137 | SequencedWorkerPool::BLOCK_SHUTDOWN); |
| 138 | SignalWorkerDone(id); |
| 139 | } |
| 140 | |
erikchen | eae82f2 | 2015-02-26 19:37:42 | [diff] [blame] | 141 | // This task posts itself back onto the SequencedWorkerPool before it |
| 142 | // finishes running. Each instance of the task maintains a strong reference |
| 143 | // to a DestructionDeadlockChecker. The DestructionDeadlockChecker is only |
| 144 | // destroyed when the task is destroyed without being run, which only happens |
| 145 | // during destruction of the SequencedWorkerPool. |
| 146 | void PostRepostingTask( |
| 147 | const scoped_refptr<SequencedWorkerPool>& pool, |
| 148 | const scoped_refptr<DestructionDeadlockChecker>& checker) { |
| 149 | Closure reposting_task = |
| 150 | base::Bind(&TestTracker::PostRepostingTask, this, pool, checker); |
| 151 | pool->PostWorkerTaskWithShutdownBehavior( |
| 152 | FROM_HERE, reposting_task, SequencedWorkerPool::SKIP_ON_SHUTDOWN); |
| 153 | } |
| 154 | |
erikchen | 19249bcc | 2015-03-13 22:57:37 | [diff] [blame] | 155 | // This task reposts itself back onto the SequencedWorkerPool before it |
| 156 | // finishes running. |
| 157 | void PostRepostingBlockingTask( |
| 158 | const scoped_refptr<SequencedWorkerPool>& pool, |
| 159 | const SequencedWorkerPool::SequenceToken& token) { |
| 160 | Closure reposting_task = |
| 161 | base::Bind(&TestTracker::PostRepostingBlockingTask, this, pool, token); |
| 162 | pool->PostSequencedWorkerTaskWithShutdownBehavior(token, |
| 163 | FROM_HERE, reposting_task, SequencedWorkerPool::BLOCK_SHUTDOWN); |
| 164 | } |
| 165 | |
erikchen | 8982d90 | 2015-03-31 01:06:46 | [diff] [blame] | 166 | void PostBlockingTaskThenUnblockThreads( |
| 167 | const scoped_refptr<SequencedWorkerPool>& pool, |
| 168 | ThreadBlocker* blocker, |
| 169 | size_t threads_to_wake) { |
| 170 | Closure arbitrary_task = base::Bind(&TestTracker::FastTask, this, 0); |
| 171 | pool->PostWorkerTaskWithShutdownBehavior( |
| 172 | FROM_HERE, arbitrary_task, SequencedWorkerPool::BLOCK_SHUTDOWN); |
| 173 | blocker->Unblock(threads_to_wake); |
| 174 | } |
| 175 | |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 176 | // Waits until the given number of tasks have started executing. |
| 177 | void WaitUntilTasksBlocked(size_t count) { |
| 178 | { |
| 179 | base::AutoLock lock(lock_); |
| 180 | while (started_events_ < count) |
| 181 | cond_var_.Wait(); |
| 182 | } |
| 183 | cond_var_.Signal(); |
| 184 | } |
| 185 | |
| 186 | // Blocks the current thread until at least the given number of tasks are in |
| 187 | // the completed vector, and then returns a copy. |
| 188 | std::vector<int> WaitUntilTasksComplete(size_t num_tasks) { |
| 189 | std::vector<int> ret; |
| 190 | { |
| 191 | base::AutoLock lock(lock_); |
| 192 | while (complete_sequence_.size() < num_tasks) |
| 193 | cond_var_.Wait(); |
| 194 | ret = complete_sequence_; |
| 195 | } |
| 196 | cond_var_.Signal(); |
| 197 | return ret; |
| 198 | } |
| 199 | |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 200 | size_t GetTasksCompletedCount() { |
| 201 | base::AutoLock lock(lock_); |
| 202 | return complete_sequence_.size(); |
| 203 | } |
| 204 | |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 205 | void ClearCompleteSequence() { |
| 206 | base::AutoLock lock(lock_); |
| 207 | complete_sequence_.clear(); |
| 208 | started_events_ = 0; |
| 209 | } |
| 210 | |
| 211 | private: |
[email protected] | a9aaa9d1 | 2012-04-25 00:42:51 | [diff] [blame] | 212 | friend class base::RefCountedThreadSafe<TestTracker>; |
| 213 | ~TestTracker() {} |
| 214 | |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 215 | void SignalWorkerDone(int id) { |
| 216 | { |
| 217 | base::AutoLock lock(lock_); |
| 218 | complete_sequence_.push_back(id); |
| 219 | } |
| 220 | cond_var_.Signal(); |
| 221 | } |
| 222 | |
| 223 | // Protects the complete_sequence. |
| 224 | base::Lock lock_; |
| 225 | |
| 226 | base::ConditionVariable cond_var_; |
| 227 | |
| 228 | // Protected by lock_. |
| 229 | std::vector<int> complete_sequence_; |
| 230 | |
| 231 | // Counter of the number of "block" workers that have started. |
| 232 | size_t started_events_; |
| 233 | }; |
| 234 | |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 235 | enum class SequencedWorkerPoolRedirection { NONE, TO_TASK_SCHEDULER }; |
| 236 | |
| 237 | class SequencedWorkerPoolTest |
| 238 | : public testing::TestWithParam<SequencedWorkerPoolRedirection> { |
[email protected] | 71b18fb | 2012-03-06 14:17:34 | [diff] [blame] | 239 | public: |
| 240 | SequencedWorkerPoolTest() |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 241 | : pool_owner_(new SequencedWorkerPoolOwner(kNumWorkerThreads, "test")), |
| 242 | tracker_(new TestTracker) {} |
| 243 | |
| 244 | void SetUp() override { |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 245 | if (RedirectedToTaskScheduler()) { |
fdoray | fa6f34f | 2017-03-29 12:25:37 | [diff] [blame] | 246 | const SchedulerWorkerPoolParams worker_pool_params( |
fdoray | fa6f34f | 2017-03-29 12:25:37 | [diff] [blame] | 247 | static_cast<int>(kNumWorkerThreads), TimeDelta::Max()); |
fdoray | 00b1e72 | 2017-04-28 14:16:45 | [diff] [blame] | 248 | TaskScheduler::Create("SequencedWorkerPoolTest"); |
| 249 | TaskScheduler::GetInstance()->Start( |
| 250 | {worker_pool_params, worker_pool_params, worker_pool_params, |
| 251 | worker_pool_params}); |
fdoray | 50a3834 | 2016-11-21 20:46:04 | [diff] [blame] | 252 | |
| 253 | // Unit tests run in an environment where SequencedWorkerPool is enabled |
| 254 | // without redirection to TaskScheduler. For the current unit test, |
| 255 | // disable it and re-enable it with redirection to TaskScheduler. |
| 256 | SequencedWorkerPool::DisableForProcessForTesting(); |
| 257 | SequencedWorkerPool::EnableWithRedirectionToTaskSchedulerForProcess(); |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 258 | } |
| 259 | } |
| 260 | |
| 261 | void TearDown() override { |
| 262 | // Wait until all references to the SequencedWorkerPool are gone and destroy |
| 263 | // it. This must be done before destroying the TaskScheduler. Otherwise, the |
| 264 | // SequencedWorkerPool could try to redirect tasks to a destroyed |
| 265 | // TaskScheduler. |
| 266 | DeletePool(); |
| 267 | |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 268 | if (RedirectedToTaskScheduler()) { |
fdoray | 50a3834 | 2016-11-21 20:46:04 | [diff] [blame] | 269 | // Reset SequencedWorkerPool to its original state (i.e. enabled without |
| 270 | // redirection to TaskScheduler). |
| 271 | SequencedWorkerPool::DisableForProcessForTesting(); |
| 272 | SequencedWorkerPool::EnableForProcess(); |
| 273 | |
| 274 | // Delete the registered TaskScheduler. |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 275 | DeleteTaskScheduler(); |
| 276 | } |
[email protected] | a9aaa9d1 | 2012-04-25 00:42:51 | [diff] [blame] | 277 | } |
[email protected] | 71b18fb | 2012-03-06 14:17:34 | [diff] [blame] | 278 | |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 279 | bool RedirectedToTaskScheduler() const { |
| 280 | return GetParam() == SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER; |
| 281 | } |
| 282 | |
[email protected] | 71b18fb | 2012-03-06 14:17:34 | [diff] [blame] | 283 | const scoped_refptr<SequencedWorkerPool>& pool() { |
[email protected] | 4402478 | 2013-02-26 22:59:50 | [diff] [blame] | 284 | return pool_owner_->pool(); |
[email protected] | 71b18fb | 2012-03-06 14:17:34 | [diff] [blame] | 285 | } |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 286 | TestTracker* tracker() { return tracker_.get(); } |
| 287 | |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 288 | // Waits until no tasks are running in the SequencedWorkerPool and no |
| 289 | // reference to it remain. Then, destroys the SequencedWorkerPool. |
| 290 | void DeletePool() { pool_owner_.reset(); } |
| 291 | |
| 292 | // Destroys and unregisters the registered TaskScheduler, if any. |
| 293 | void DeleteTaskScheduler() { |
| 294 | if (TaskScheduler::GetInstance()) { |
Jeffrey He | a9a085dd | 2017-08-08 15:05:01 | [diff] [blame] | 295 | TaskScheduler::GetInstance()->FlushForTesting(); |
fdoray | 7bba05e | 2017-01-25 02:34:45 | [diff] [blame] | 296 | TaskScheduler::GetInstance()->JoinForTesting(); |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 297 | TaskScheduler::SetInstance(nullptr); |
| 298 | } |
[email protected] | 4402478 | 2013-02-26 22:59:50 | [diff] [blame] | 299 | } |
| 300 | |
[email protected] | 71b18fb | 2012-03-06 14:17:34 | [diff] [blame] | 301 | void SetWillWaitForShutdownCallback(const Closure& callback) { |
[email protected] | 4402478 | 2013-02-26 22:59:50 | [diff] [blame] | 302 | pool_owner_->SetWillWaitForShutdownCallback(callback); |
[email protected] | 71b18fb | 2012-03-06 14:17:34 | [diff] [blame] | 303 | } |
| 304 | |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 305 | // Ensures that the given number of worker threads is created by adding |
| 306 | // tasks and waiting until they complete. Worker thread creation is |
| 307 | // serialized, can happen on background threads asynchronously, and doesn't |
| 308 | // happen any more at shutdown. This means that if a test posts a bunch of |
| 309 | // tasks and calls shutdown, fewer workers will be created than the test may |
| 310 | // expect. |
| 311 | // |
| 312 | // This function ensures that this condition can't happen so tests can make |
| 313 | // assumptions about the number of workers active. See the comment in |
| 314 | // PrepareToStartAdditionalThreadIfNecessary in the .cc file for more |
| 315 | // details. |
| 316 | // |
| 317 | // It will post tasks to the queue with id -1. It also assumes this is the |
| 318 | // first thing called in a test since it will clear the complete_sequence_. |
| 319 | void EnsureAllWorkersCreated() { |
| 320 | // Create a bunch of threads, all waiting. This will cause that may |
| 321 | // workers to be created. |
| 322 | ThreadBlocker blocker; |
| 323 | for (size_t i = 0; i < kNumWorkerThreads; i++) { |
sdefresne | 3f731c7 | 2017-05-30 12:52:52 | [diff] [blame] | 324 | pool()->PostWorkerTask( |
| 325 | FROM_HERE, |
| 326 | base::BindOnce(&TestTracker::BlockTask, tracker(), -1, &blocker)); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 327 | } |
| 328 | tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); |
| 329 | |
| 330 | // Now wake them up and wait until they're done. |
| 331 | blocker.Unblock(kNumWorkerThreads); |
| 332 | tracker()->WaitUntilTasksComplete(kNumWorkerThreads); |
| 333 | |
| 334 | // Clean up the task IDs we added. |
| 335 | tracker()->ClearCompleteSequence(); |
| 336 | } |
| 337 | |
[email protected] | 88bbd81 | 2012-03-14 23:17:00 | [diff] [blame] | 338 | int has_work_call_count() const { |
[email protected] | 4402478 | 2013-02-26 22:59:50 | [diff] [blame] | 339 | return pool_owner_->has_work_call_count(); |
[email protected] | 88bbd81 | 2012-03-14 23:17:00 | [diff] [blame] | 340 | } |
| 341 | |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 342 | private: |
[email protected] | 71b18fb | 2012-03-06 14:17:34 | [diff] [blame] | 343 | MessageLoop message_loop_; |
dcheng | 093de9b | 2016-04-04 21:25:51 | [diff] [blame] | 344 | std::unique_ptr<SequencedWorkerPoolOwner> pool_owner_; |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 345 | const scoped_refptr<TestTracker> tracker_; |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 346 | }; |
| 347 | |
| 348 | // Checks that the given number of entries are in the tasks to complete of |
| 349 | // the given tracker, and then signals the given event the given number of |
erikchen | 8982d90 | 2015-03-31 01:06:46 | [diff] [blame] | 350 | // times. This is used to wake up blocked background threads before blocking |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 351 | // on shutdown. |
| 352 | void EnsureTasksToCompleteCountAndUnblock(scoped_refptr<TestTracker> tracker, |
| 353 | size_t expected_tasks_to_complete, |
| 354 | ThreadBlocker* blocker, |
| 355 | size_t threads_to_awake) { |
| 356 | EXPECT_EQ( |
| 357 | expected_tasks_to_complete, |
| 358 | tracker->WaitUntilTasksComplete(expected_tasks_to_complete).size()); |
| 359 | |
| 360 | blocker->Unblock(threads_to_awake); |
| 361 | } |
| 362 | |
[email protected] | 4402478 | 2013-02-26 22:59:50 | [diff] [blame] | 363 | class DeletionHelper : public base::RefCountedThreadSafe<DeletionHelper> { |
| 364 | public: |
| 365 | explicit DeletionHelper( |
| 366 | const scoped_refptr<base::RefCountedData<bool> >& deleted_flag) |
| 367 | : deleted_flag_(deleted_flag) { |
| 368 | } |
| 369 | |
| 370 | private: |
| 371 | friend class base::RefCountedThreadSafe<DeletionHelper>; |
| 372 | virtual ~DeletionHelper() { deleted_flag_->data = true; } |
| 373 | |
| 374 | const scoped_refptr<base::RefCountedData<bool> > deleted_flag_; |
| 375 | DISALLOW_COPY_AND_ASSIGN(DeletionHelper); |
| 376 | }; |
| 377 | |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 378 | void ShouldNotRun(const scoped_refptr<DeletionHelper>& helper) { |
[email protected] | 4402478 | 2013-02-26 22:59:50 | [diff] [blame] | 379 | ADD_FAILURE() << "Should never run"; |
| 380 | } |
| 381 | |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 382 | // Tests that shutdown does not wait for delayed tasks. |
| 383 | TEST_P(SequencedWorkerPoolTest, DelayedTaskDuringShutdown) { |
[email protected] | 4402478 | 2013-02-26 22:59:50 | [diff] [blame] | 384 | // Post something to verify the pool is started up. |
| 385 | EXPECT_TRUE(pool()->PostTask( |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 386 | FROM_HERE, base::BindOnce(&TestTracker::FastTask, tracker(), 1))); |
[email protected] | 4402478 | 2013-02-26 22:59:50 | [diff] [blame] | 387 | |
| 388 | scoped_refptr<base::RefCountedData<bool> > deleted_flag( |
| 389 | new base::RefCountedData<bool>(false)); |
| 390 | |
| 391 | base::Time posted_at(base::Time::Now()); |
| 392 | // Post something that shouldn't run. |
| 393 | EXPECT_TRUE(pool()->PostDelayedTask( |
| 394 | FROM_HERE, |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 395 | base::BindOnce(&ShouldNotRun, |
kylechar | 96f3eba | 2017-09-25 20:23:56 | [diff] [blame] | 396 | MakeRefCounted<DeletionHelper>(deleted_flag)), |
[email protected] | 4402478 | 2013-02-26 22:59:50 | [diff] [blame] | 397 | TestTimeouts::action_timeout())); |
| 398 | |
| 399 | std::vector<int> completion_sequence = tracker()->WaitUntilTasksComplete(1); |
| 400 | ASSERT_EQ(1u, completion_sequence.size()); |
| 401 | ASSERT_EQ(1, completion_sequence[0]); |
| 402 | |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 403 | // Shutdown the pool. |
| 404 | pool()->Shutdown(); |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 405 | if (RedirectedToTaskScheduler()) |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 406 | TaskScheduler::GetInstance()->Shutdown(); |
[email protected] | 4402478 | 2013-02-26 22:59:50 | [diff] [blame] | 407 | |
| 408 | // Verify that we didn't block until the task was due. |
| 409 | ASSERT_LT(base::Time::Now() - posted_at, TestTimeouts::action_timeout()); |
| 410 | |
fdoray | dc7bca9 | 2016-09-22 14:55:44 | [diff] [blame] | 411 | // TaskScheduler shouldn't delete the delayed task before it is itself |
| 412 | // deleted. SequencedWorkerPool starts deleting tasks as soon as its |
| 413 | // Shutdown() method is called (see SequencedWorkerPool::Inner::GetWork). |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 414 | if (RedirectedToTaskScheduler()) |
fdoray | dc7bca9 | 2016-09-22 14:55:44 | [diff] [blame] | 415 | EXPECT_FALSE(deleted_flag->data); |
| 416 | |
| 417 | // Verify that the delayed task is deleted once the SequencedWorkerPool (and |
| 418 | // the TaskScheduler when applicable) have been deleted. |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 419 | DeletePool(); |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 420 | if (RedirectedToTaskScheduler()) |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 421 | DeleteTaskScheduler(); |
| 422 | EXPECT_TRUE(deleted_flag->data); |
[email protected] | 4402478 | 2013-02-26 22:59:50 | [diff] [blame] | 423 | } |
| 424 | |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 425 | // Tests that same-named tokens have the same ID. |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 426 | TEST_P(SequencedWorkerPoolTest, NamedTokens) { |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 427 | const std::string name1("hello"); |
| 428 | SequencedWorkerPool::SequenceToken token1 = |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 429 | pool()->GetNamedSequenceToken(name1); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 430 | |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 431 | SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken(); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 432 | |
| 433 | const std::string name3("goodbye"); |
| 434 | SequencedWorkerPool::SequenceToken token3 = |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 435 | pool()->GetNamedSequenceToken(name3); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 436 | |
| 437 | // All 3 tokens should be different. |
| 438 | EXPECT_FALSE(token1.Equals(token2)); |
| 439 | EXPECT_FALSE(token1.Equals(token3)); |
| 440 | EXPECT_FALSE(token2.Equals(token3)); |
| 441 | |
| 442 | // Requesting the same name again should give the same value. |
| 443 | SequencedWorkerPool::SequenceToken token1again = |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 444 | pool()->GetNamedSequenceToken(name1); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 445 | EXPECT_TRUE(token1.Equals(token1again)); |
| 446 | |
| 447 | SequencedWorkerPool::SequenceToken token3again = |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 448 | pool()->GetNamedSequenceToken(name3); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 449 | EXPECT_TRUE(token3.Equals(token3again)); |
| 450 | } |
| 451 | |
| 452 | // Tests that posting a bunch of tasks (many more than the number of worker |
| 453 | // threads) runs them all. |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 454 | TEST_P(SequencedWorkerPoolTest, LotsOfTasks) { |
sdefresne | 3f731c7 | 2017-05-30 12:52:52 | [diff] [blame] | 455 | pool()->PostWorkerTask(FROM_HERE, |
| 456 | base::BindOnce(&TestTracker::SlowTask, tracker(), 0)); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 457 | |
| 458 | const size_t kNumTasks = 20; |
| 459 | for (size_t i = 1; i < kNumTasks; i++) { |
sdefresne | 3f731c7 | 2017-05-30 12:52:52 | [diff] [blame] | 460 | pool()->PostWorkerTask( |
| 461 | FROM_HERE, base::BindOnce(&TestTracker::FastTask, tracker(), i)); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 462 | } |
| 463 | |
| 464 | std::vector<int> result = tracker()->WaitUntilTasksComplete(kNumTasks); |
| 465 | EXPECT_EQ(kNumTasks, result.size()); |
| 466 | } |
| 467 | |
[email protected] | 1848125 | 2012-02-29 21:05:16 | [diff] [blame] | 468 | // Tests that posting a bunch of tasks (many more than the number of |
| 469 | // worker threads) to two pools simultaneously runs them all twice. |
| 470 | // This test is meant to shake out any concurrency issues between |
| 471 | // pools (like histograms). |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 472 | TEST_P(SequencedWorkerPoolTest, LotsOfTasksTwoPools) { |
[email protected] | 71b18fb | 2012-03-06 14:17:34 | [diff] [blame] | 473 | SequencedWorkerPoolOwner pool1(kNumWorkerThreads, "test1"); |
| 474 | SequencedWorkerPoolOwner pool2(kNumWorkerThreads, "test2"); |
[email protected] | 1848125 | 2012-02-29 21:05:16 | [diff] [blame] | 475 | |
| 476 | base::Closure slow_task = base::Bind(&TestTracker::SlowTask, tracker(), 0); |
sdefresne | 3f731c7 | 2017-05-30 12:52:52 | [diff] [blame] | 477 | pool1.pool()->PostWorkerTask(FROM_HERE, slow_task); |
| 478 | pool2.pool()->PostWorkerTask(FROM_HERE, slow_task); |
[email protected] | 1848125 | 2012-02-29 21:05:16 | [diff] [blame] | 479 | |
| 480 | const size_t kNumTasks = 20; |
| 481 | for (size_t i = 1; i < kNumTasks; i++) { |
| 482 | base::Closure fast_task = |
| 483 | base::Bind(&TestTracker::FastTask, tracker(), i); |
sdefresne | 3f731c7 | 2017-05-30 12:52:52 | [diff] [blame] | 484 | pool1.pool()->PostWorkerTask(FROM_HERE, fast_task); |
| 485 | pool2.pool()->PostWorkerTask(FROM_HERE, fast_task); |
[email protected] | 1848125 | 2012-02-29 21:05:16 | [diff] [blame] | 486 | } |
| 487 | |
| 488 | std::vector<int> result = |
| 489 | tracker()->WaitUntilTasksComplete(2*kNumTasks); |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 490 | EXPECT_EQ(2 * kNumTasks, result.size()); |
[email protected] | 1848125 | 2012-02-29 21:05:16 | [diff] [blame] | 491 | } |
| 492 | |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 493 | // Test that tasks with the same sequence token are executed in order but don't |
| 494 | // affect other tasks. |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 495 | TEST_P(SequencedWorkerPoolTest, Sequence) { |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 496 | // Fill all the worker threads except one. |
| 497 | const size_t kNumBackgroundTasks = kNumWorkerThreads - 1; |
| 498 | ThreadBlocker background_blocker; |
| 499 | for (size_t i = 0; i < kNumBackgroundTasks; i++) { |
sdefresne | 3f731c7 | 2017-05-30 12:52:52 | [diff] [blame] | 500 | pool()->PostWorkerTask(FROM_HERE, |
| 501 | base::BindOnce(&TestTracker::BlockTask, tracker(), i, |
| 502 | &background_blocker)); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 503 | } |
| 504 | tracker()->WaitUntilTasksBlocked(kNumBackgroundTasks); |
| 505 | |
| 506 | // Create two tasks with the same sequence token, one that will block on the |
| 507 | // event, and one which will just complete quickly when it's run. Since there |
| 508 | // is one worker thread free, the first task will start and then block, and |
| 509 | // the second task should be waiting. |
| 510 | ThreadBlocker blocker; |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 511 | SequencedWorkerPool::SequenceToken token1 = pool()->GetSequenceToken(); |
| 512 | pool()->PostSequencedWorkerTask( |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 513 | token1, FROM_HERE, |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 514 | base::BindOnce(&TestTracker::BlockTask, tracker(), 100, &blocker)); |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 515 | pool()->PostSequencedWorkerTask( |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 516 | token1, FROM_HERE, |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 517 | base::BindOnce(&TestTracker::FastTask, tracker(), 101)); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 518 | EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size()); |
| 519 | |
| 520 | // Create another two tasks as above with a different token. These will be |
| 521 | // blocked since there are no slots to run. |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 522 | SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken(); |
| 523 | pool()->PostSequencedWorkerTask( |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 524 | token2, FROM_HERE, |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 525 | base::BindOnce(&TestTracker::FastTask, tracker(), 200)); |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 526 | pool()->PostSequencedWorkerTask( |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 527 | token2, FROM_HERE, |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 528 | base::BindOnce(&TestTracker::FastTask, tracker(), 201)); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 529 | EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size()); |
| 530 | |
| 531 | // Let one background task complete. This should then let both tasks of |
| 532 | // token2 run to completion in order. The second task of token1 should still |
| 533 | // be blocked. |
| 534 | background_blocker.Unblock(1); |
| 535 | std::vector<int> result = tracker()->WaitUntilTasksComplete(3); |
| 536 | ASSERT_EQ(3u, result.size()); |
| 537 | EXPECT_EQ(200, result[1]); |
| 538 | EXPECT_EQ(201, result[2]); |
| 539 | |
| 540 | // Finish the rest of the background tasks. This should leave some workers |
| 541 | // free with the second token1 task still blocked on the first. |
| 542 | background_blocker.Unblock(kNumBackgroundTasks - 1); |
| 543 | EXPECT_EQ(kNumBackgroundTasks + 2, |
| 544 | tracker()->WaitUntilTasksComplete(kNumBackgroundTasks + 2).size()); |
| 545 | |
| 546 | // Allow the first task of token1 to complete. This should run the second. |
| 547 | blocker.Unblock(1); |
| 548 | result = tracker()->WaitUntilTasksComplete(kNumBackgroundTasks + 4); |
| 549 | ASSERT_EQ(kNumBackgroundTasks + 4, result.size()); |
| 550 | EXPECT_EQ(100, result[result.size() - 2]); |
| 551 | EXPECT_EQ(101, result[result.size() - 1]); |
| 552 | } |
| 553 | |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 554 | // Tests that any tasks posted after Shutdown are ignored. |
[email protected] | c01c264 | 2013-01-15 18:49:32 | [diff] [blame] | 555 | // Disabled for flakiness. See http://crbug.com/166451. |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 556 | TEST_P(SequencedWorkerPoolTest, DISABLED_IgnoresAfterShutdown) { |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 557 | // Start tasks to take all the threads and block them. |
| 558 | EnsureAllWorkersCreated(); |
| 559 | ThreadBlocker blocker; |
| 560 | for (size_t i = 0; i < kNumWorkerThreads; i++) { |
sdefresne | 3f731c7 | 2017-05-30 12:52:52 | [diff] [blame] | 561 | pool()->PostWorkerTask(FROM_HERE, base::BindOnce(&TestTracker::BlockTask, |
| 562 | tracker(), i, &blocker)); |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 563 | } |
| 564 | tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); |
| 565 | |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 566 | SetWillWaitForShutdownCallback( |
| 567 | base::Bind(&EnsureTasksToCompleteCountAndUnblock, |
| 568 | scoped_refptr<TestTracker>(tracker()), 0, |
| 569 | &blocker, kNumWorkerThreads)); |
[email protected] | 270f2cf | 2012-12-19 01:56:37 | [diff] [blame] | 570 | |
| 571 | // Shutdown the worker pool. This should discard all non-blocking tasks. |
| 572 | const int kMaxNewBlockingTasksAfterShutdown = 100; |
| 573 | pool()->Shutdown(kMaxNewBlockingTasksAfterShutdown); |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 574 | |
| 575 | int old_has_work_call_count = has_work_call_count(); |
| 576 | |
| 577 | std::vector<int> result = |
| 578 | tracker()->WaitUntilTasksComplete(kNumWorkerThreads); |
| 579 | |
[email protected] | 270f2cf | 2012-12-19 01:56:37 | [diff] [blame] | 580 | // The kNumWorkerThread items should have completed, in no particular order. |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 581 | ASSERT_EQ(kNumWorkerThreads, result.size()); |
thestig | 6c335d4 | 2015-12-07 18:25:34 | [diff] [blame] | 582 | for (size_t i = 0; i < kNumWorkerThreads; i++) |
| 583 | EXPECT_TRUE(ContainsValue(result, static_cast<int>(i))); |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 584 | |
| 585 | // No further tasks, regardless of shutdown mode, should be allowed. |
| 586 | EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 587 | FROM_HERE, base::BindOnce(&TestTracker::FastTask, tracker(), 100), |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 588 | SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); |
| 589 | EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 590 | FROM_HERE, base::BindOnce(&TestTracker::FastTask, tracker(), 101), |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 591 | SequencedWorkerPool::SKIP_ON_SHUTDOWN)); |
| 592 | EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 593 | FROM_HERE, base::BindOnce(&TestTracker::FastTask, tracker(), 102), |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 594 | SequencedWorkerPool::BLOCK_SHUTDOWN)); |
| 595 | |
| 596 | ASSERT_EQ(old_has_work_call_count, has_work_call_count()); |
| 597 | } |
| 598 | |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 599 | TEST_P(SequencedWorkerPoolTest, AllowsAfterShutdown) { |
[email protected] | 270f2cf | 2012-12-19 01:56:37 | [diff] [blame] | 600 | // Test that <n> new blocking tasks are allowed provided they're posted |
| 601 | // by a running tasks. |
| 602 | EnsureAllWorkersCreated(); |
| 603 | ThreadBlocker blocker; |
| 604 | |
| 605 | // Start tasks to take all the threads and block them. |
| 606 | const int kNumBlockTasks = static_cast<int>(kNumWorkerThreads); |
| 607 | for (int i = 0; i < kNumBlockTasks; ++i) { |
sdefresne | 3f731c7 | 2017-05-30 12:52:52 | [diff] [blame] | 608 | EXPECT_TRUE(pool()->PostWorkerTask( |
[email protected] | 270f2cf | 2012-12-19 01:56:37 | [diff] [blame] | 609 | FROM_HERE, |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 610 | base::BindOnce(&TestTracker::BlockTask, tracker(), i, &blocker))); |
[email protected] | 270f2cf | 2012-12-19 01:56:37 | [diff] [blame] | 611 | } |
| 612 | tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); |
| 613 | |
| 614 | // Queue up shutdown blocking tasks behind those which will attempt to post |
fdoray | 387159105 | 2016-10-04 13:53:39 | [diff] [blame] | 615 | // additional tasks when run, PostAdditionalTasks attempts to post 3 |
[email protected] | 270f2cf | 2012-12-19 01:56:37 | [diff] [blame] | 616 | // new FastTasks, one for each shutdown_behavior. |
| 617 | const int kNumQueuedTasks = static_cast<int>(kNumWorkerThreads); |
| 618 | for (int i = 0; i < kNumQueuedTasks; ++i) { |
| 619 | EXPECT_TRUE(pool()->PostWorkerTaskWithShutdownBehavior( |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 620 | FROM_HERE, |
| 621 | base::BindOnce(&TestTracker::PostAdditionalTasks, tracker(), i, |
| 622 | base::RetainedRef(pool()), false), |
[email protected] | 270f2cf | 2012-12-19 01:56:37 | [diff] [blame] | 623 | SequencedWorkerPool::BLOCK_SHUTDOWN)); |
| 624 | } |
| 625 | |
fdoray | 387159105 | 2016-10-04 13:53:39 | [diff] [blame] | 626 | // Half the additional blocking tasks will be allowed to run. |
| 627 | constexpr int kNumNewBlockingTasksToAllow = kNumWorkerThreads / 2; |
[email protected] | 270f2cf | 2012-12-19 01:56:37 | [diff] [blame] | 628 | |
fdoray | 387159105 | 2016-10-04 13:53:39 | [diff] [blame] | 629 | if (RedirectedToTaskScheduler()) { |
| 630 | // When redirection to TaskScheduler is enabled, |
| 631 | // SequencedWorkerPool::Shutdown() sets the number of additional |
| 632 | // BLOCK_SHUTDOWN tasks that can be posted and returns without waiting for |
| 633 | // pending BLOCK_SHUTDOWN tasks to complete their execution. |
| 634 | pool()->Shutdown(kNumNewBlockingTasksToAllow); |
| 635 | |
| 636 | // Unblock tasks. |
| 637 | EnsureTasksToCompleteCountAndUnblock(tracker(), 0, &blocker, |
| 638 | kNumBlockTasks); |
| 639 | |
| 640 | // TaskScheduler::Shutdown() waits for pending BLOCK_SHUTDOWN tasks to |
| 641 | // complete their execution. |
| 642 | TaskScheduler::GetInstance()->Shutdown(); |
| 643 | } else { |
| 644 | // Once shutdown starts, unblock tasks. |
| 645 | SetWillWaitForShutdownCallback(base::Bind( |
| 646 | &EnsureTasksToCompleteCountAndUnblock, |
| 647 | scoped_refptr<TestTracker>(tracker()), 0, &blocker, kNumBlockTasks)); |
| 648 | |
| 649 | // Set the number of additional BLOCK_SHUTDOWN tasks that can be posted and |
| 650 | // wait for pending BLOCK_SHUTDOWN tasks to complete their execution. |
| 651 | pool()->Shutdown(kNumNewBlockingTasksToAllow); |
| 652 | } |
[email protected] | 270f2cf | 2012-12-19 01:56:37 | [diff] [blame] | 653 | |
| 654 | // Ensure that the correct number of tasks actually got run. |
| 655 | tracker()->WaitUntilTasksComplete(static_cast<size_t>( |
| 656 | kNumBlockTasks + kNumQueuedTasks + kNumNewBlockingTasksToAllow)); |
| 657 | |
| 658 | // Clean up the task IDs we added and go home. |
| 659 | tracker()->ClearCompleteSequence(); |
| 660 | } |
| 661 | |
erikchen | 8982d90 | 2015-03-31 01:06:46 | [diff] [blame] | 662 | // Tests that blocking tasks can still be posted during shutdown, as long as |
| 663 | // the task is not being posted within the context of a running task. |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 664 | TEST_P(SequencedWorkerPoolTest, |
erikchen | 8982d90 | 2015-03-31 01:06:46 | [diff] [blame] | 665 | AllowsBlockingTasksDuringShutdownOutsideOfRunningTask) { |
| 666 | EnsureAllWorkersCreated(); |
| 667 | ThreadBlocker blocker; |
| 668 | |
| 669 | // Start tasks to take all the threads and block them. |
| 670 | const int kNumBlockTasks = static_cast<int>(kNumWorkerThreads); |
| 671 | for (int i = 0; i < kNumBlockTasks; ++i) { |
sdefresne | 3f731c7 | 2017-05-30 12:52:52 | [diff] [blame] | 672 | EXPECT_TRUE(pool()->PostWorkerTask( |
erikchen | 8982d90 | 2015-03-31 01:06:46 | [diff] [blame] | 673 | FROM_HERE, |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 674 | base::BindOnce(&TestTracker::BlockTask, tracker(), i, &blocker))); |
erikchen | 8982d90 | 2015-03-31 01:06:46 | [diff] [blame] | 675 | } |
| 676 | tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); |
| 677 | |
fdoray | 387159105 | 2016-10-04 13:53:39 | [diff] [blame] | 678 | constexpr int kNumNewBlockingTasksToAllow = 1; |
| 679 | |
| 680 | if (RedirectedToTaskScheduler()) { |
| 681 | // When redirection to TaskScheduler is enabled, |
| 682 | // SequencedWorkerPool::Shutdown() sets the number of additional |
| 683 | // BLOCK_SHUTDOWN tasks that can be posted and returns without waiting for |
| 684 | // pending BLOCK_SHUTDOWN tasks to complete their execution. |
| 685 | pool()->Shutdown(kNumNewBlockingTasksToAllow); |
| 686 | |
| 687 | // Post a blocking task and unblock tasks. |
| 688 | tracker()->PostBlockingTaskThenUnblockThreads(pool(), &blocker, |
| 689 | kNumWorkerThreads); |
| 690 | |
| 691 | // TaskScheduler::Shutdown() waits for pending BLOCK_SHUTDOWN tasks to |
| 692 | // complete their execution. |
| 693 | TaskScheduler::GetInstance()->Shutdown(); |
| 694 | } else { |
| 695 | // Once shutdown starts, post a blocking task and unblock tasks. |
| 696 | SetWillWaitForShutdownCallback( |
| 697 | base::Bind(&TestTracker::PostBlockingTaskThenUnblockThreads, |
| 698 | scoped_refptr<TestTracker>(tracker()), pool(), &blocker, |
| 699 | kNumWorkerThreads)); |
| 700 | |
| 701 | // Set the number of additional BLOCK_SHUTDOWN tasks that can be posted and |
| 702 | // wait for pending BLOCK_SHUTDOWN tasks to complete their execution. |
| 703 | pool()->Shutdown(kNumNewBlockingTasksToAllow); |
| 704 | } |
erikchen | 8982d90 | 2015-03-31 01:06:46 | [diff] [blame] | 705 | |
| 706 | // Ensure that the correct number of tasks actually got run. |
fdoray | 387159105 | 2016-10-04 13:53:39 | [diff] [blame] | 707 | tracker()->WaitUntilTasksComplete( |
| 708 | static_cast<size_t>(kNumWorkerThreads + kNumNewBlockingTasksToAllow)); |
erikchen | 8982d90 | 2015-03-31 01:06:46 | [diff] [blame] | 709 | tracker()->ClearCompleteSequence(); |
| 710 | } |
| 711 | |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 712 | // Tests that unrun tasks are discarded properly according to their shutdown |
| 713 | // mode. |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 714 | TEST_P(SequencedWorkerPoolTest, DiscardOnShutdown) { |
| 715 | // As tested by |
| 716 | // TaskSchedulerTaskTrackerTest.WillPostBeforeShutdownRunDuringShutdown, on |
| 717 | // shutdown, the TaskScheduler discards SKIP_ON_SHUTDOWN and |
| 718 | // CONTINUE_ON_SHUTDOWN tasks and runs BLOCK_SHUTDOWN tasks. However, since it |
| 719 | // doesn't provide a way to run a callback from inside its Shutdown() method, |
| 720 | // it would be hard to make this test work with redirection enabled. |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 721 | if (RedirectedToTaskScheduler()) |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 722 | return; |
| 723 | |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 724 | // Start tasks to take all the threads and block them. |
| 725 | EnsureAllWorkersCreated(); |
| 726 | ThreadBlocker blocker; |
| 727 | for (size_t i = 0; i < kNumWorkerThreads; i++) { |
sdefresne | 3f731c7 | 2017-05-30 12:52:52 | [diff] [blame] | 728 | pool()->PostWorkerTask(FROM_HERE, base::BindOnce(&TestTracker::BlockTask, |
| 729 | tracker(), i, &blocker)); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 730 | } |
| 731 | tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); |
| 732 | |
| 733 | // Create some tasks with different shutdown modes. |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 734 | pool()->PostWorkerTaskWithShutdownBehavior( |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 735 | FROM_HERE, base::BindOnce(&TestTracker::FastTask, tracker(), 100), |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 736 | SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 737 | pool()->PostWorkerTaskWithShutdownBehavior( |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 738 | FROM_HERE, base::BindOnce(&TestTracker::FastTask, tracker(), 101), |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 739 | SequencedWorkerPool::SKIP_ON_SHUTDOWN); |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 740 | pool()->PostWorkerTaskWithShutdownBehavior( |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 741 | FROM_HERE, base::BindOnce(&TestTracker::FastTask, tracker(), 102), |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 742 | SequencedWorkerPool::BLOCK_SHUTDOWN); |
| 743 | |
| 744 | // Shutdown the worker pool. This should discard all non-blocking tasks. |
[email protected] | 71b18fb | 2012-03-06 14:17:34 | [diff] [blame] | 745 | SetWillWaitForShutdownCallback( |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 746 | base::Bind(&EnsureTasksToCompleteCountAndUnblock, |
| 747 | scoped_refptr<TestTracker>(tracker()), 0, |
[email protected] | 71b18fb | 2012-03-06 14:17:34 | [diff] [blame] | 748 | &blocker, kNumWorkerThreads)); |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 749 | pool()->Shutdown(); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 750 | |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 751 | std::vector<int> result = |
| 752 | tracker()->WaitUntilTasksComplete(kNumWorkerThreads + 1); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 753 | |
| 754 | // The kNumWorkerThread items should have completed, plus the BLOCK_SHUTDOWN |
| 755 | // one, in no particular order. |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 756 | ASSERT_EQ(kNumWorkerThreads + 1, result.size()); |
thestig | 6c335d4 | 2015-12-07 18:25:34 | [diff] [blame] | 757 | for (size_t i = 0; i < kNumWorkerThreads; i++) |
| 758 | EXPECT_TRUE(ContainsValue(result, static_cast<int>(i))); |
| 759 | EXPECT_TRUE(ContainsValue(result, 102)); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 760 | } |
| 761 | |
| 762 | // Tests that CONTINUE_ON_SHUTDOWN tasks don't block shutdown. |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 763 | TEST_P(SequencedWorkerPoolTest, ContinueOnShutdown) { |
[email protected] | 497ec46 | 2012-04-11 22:42:29 | [diff] [blame] | 764 | scoped_refptr<TaskRunner> runner(pool()->GetTaskRunnerWithShutdownBehavior( |
| 765 | SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); |
| 766 | scoped_refptr<SequencedTaskRunner> sequenced_runner( |
| 767 | pool()->GetSequencedTaskRunnerWithShutdownBehavior( |
| 768 | pool()->GetSequenceToken(), |
| 769 | SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 770 | EnsureAllWorkersCreated(); |
| 771 | ThreadBlocker blocker; |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 772 | pool()->PostWorkerTaskWithShutdownBehavior( |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 773 | FROM_HERE, |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 774 | base::BindOnce(&TestTracker::BlockTask, tracker(), 0, &blocker), |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 775 | SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 776 | runner->PostTask(FROM_HERE, base::BindOnce(&TestTracker::BlockTask, tracker(), |
| 777 | 1, &blocker)); |
| 778 | sequenced_runner->PostTask(FROM_HERE, base::BindOnce(&TestTracker::BlockTask, |
| 779 | tracker(), 2, &blocker)); |
[email protected] | 497ec46 | 2012-04-11 22:42:29 | [diff] [blame] | 780 | |
| 781 | tracker()->WaitUntilTasksBlocked(3); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 782 | |
| 783 | // This should not block. If this test hangs, it means it failed. |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 784 | pool()->Shutdown(); |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 785 | if (RedirectedToTaskScheduler()) |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 786 | TaskScheduler::GetInstance()->Shutdown(); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 787 | |
| 788 | // The task should not have completed yet. |
| 789 | EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size()); |
| 790 | |
| 791 | // Posting more tasks should fail. |
[email protected] | e3f7624 | 2012-02-27 23:09:57 | [diff] [blame] | 792 | EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior( |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 793 | FROM_HERE, base::BindOnce(&TestTracker::FastTask, tracker(), 0), |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 794 | SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)); |
[email protected] | 497ec46 | 2012-04-11 22:42:29 | [diff] [blame] | 795 | EXPECT_FALSE(runner->PostTask( |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 796 | FROM_HERE, base::BindOnce(&TestTracker::FastTask, tracker(), 0))); |
[email protected] | 497ec46 | 2012-04-11 22:42:29 | [diff] [blame] | 797 | EXPECT_FALSE(sequenced_runner->PostTask( |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 798 | FROM_HERE, base::BindOnce(&TestTracker::FastTask, tracker(), 0))); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 799 | |
[email protected] | 497ec46 | 2012-04-11 22:42:29 | [diff] [blame] | 800 | // Continue the background thread and make sure the tasks can complete. |
| 801 | blocker.Unblock(3); |
| 802 | std::vector<int> result = tracker()->WaitUntilTasksComplete(3); |
| 803 | EXPECT_EQ(3u, result.size()); |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 804 | } |
| 805 | |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 806 | // Tests that SKIP_ON_SHUTDOWN tasks that have been started block Shutdown |
| 807 | // until they stop, but tasks not yet started do not. |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 808 | TEST_P(SequencedWorkerPoolTest, SkipOnShutdown) { |
| 809 | // As tested by |
| 810 | // TaskSchedulerTaskTrackerTest.WillPostAndRunLongTaskBeforeShutdown and |
| 811 | // TaskSchedulerTaskTrackerTest.WillPostBeforeShutdownRunDuringShutdown, the |
| 812 | // TaskScheduler correctly handles SKIP_ON_SHUTDOWN tasks. However, since it |
| 813 | // doesn't provide a way to run a callback from inside its Shutdown() method, |
| 814 | // it would be hard to make this test work with redirection enabled. |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 815 | if (RedirectedToTaskScheduler()) |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 816 | return; |
| 817 | |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 818 | // Start tasks to take all the threads and block them. |
| 819 | EnsureAllWorkersCreated(); |
| 820 | ThreadBlocker blocker; |
| 821 | |
| 822 | // Now block all the threads with SKIP_ON_SHUTDOWN. Shutdown() should not |
| 823 | // return until these tasks have completed. |
| 824 | for (size_t i = 0; i < kNumWorkerThreads; i++) { |
| 825 | pool()->PostWorkerTaskWithShutdownBehavior( |
| 826 | FROM_HERE, |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 827 | base::BindOnce(&TestTracker::BlockTask, tracker(), i, &blocker), |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 828 | SequencedWorkerPool::SKIP_ON_SHUTDOWN); |
| 829 | } |
| 830 | tracker()->WaitUntilTasksBlocked(kNumWorkerThreads); |
| 831 | |
| 832 | // Now post an additional task as SKIP_ON_SHUTDOWN, which should not be |
| 833 | // executed once Shutdown() has been called. |
| 834 | pool()->PostWorkerTaskWithShutdownBehavior( |
| 835 | FROM_HERE, |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 836 | base::BindOnce(&TestTracker::BlockTask, tracker(), 0, &blocker), |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 837 | SequencedWorkerPool::SKIP_ON_SHUTDOWN); |
| 838 | |
| 839 | // This callback will only be invoked if SKIP_ON_SHUTDOWN tasks that have |
| 840 | // been started block shutdown. |
| 841 | SetWillWaitForShutdownCallback( |
| 842 | base::Bind(&EnsureTasksToCompleteCountAndUnblock, |
| 843 | scoped_refptr<TestTracker>(tracker()), 0, |
| 844 | &blocker, kNumWorkerThreads)); |
| 845 | |
| 846 | // No tasks should have completed yet. |
| 847 | EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size()); |
| 848 | |
| 849 | // This should not block. If this test hangs, it means it failed. |
| 850 | pool()->Shutdown(); |
| 851 | |
| 852 | // Shutdown should not return until all of the tasks have completed. |
| 853 | std::vector<int> result = |
| 854 | tracker()->WaitUntilTasksComplete(kNumWorkerThreads); |
| 855 | |
| 856 | // Only tasks marked SKIP_ON_SHUTDOWN that were already started should be |
| 857 | // allowed to complete. No additional non-blocking tasks should have been |
| 858 | // started. |
| 859 | ASSERT_EQ(kNumWorkerThreads, result.size()); |
thestig | 6c335d4 | 2015-12-07 18:25:34 | [diff] [blame] | 860 | for (size_t i = 0; i < kNumWorkerThreads; i++) |
| 861 | EXPECT_TRUE(ContainsValue(result, static_cast<int>(i))); |
[email protected] | bdb2e10 | 2012-07-21 04:58:04 | [diff] [blame] | 862 | } |
| 863 | |
[email protected] | 857b600 | 2012-03-12 21:42:13 | [diff] [blame] | 864 | // Ensure all worker threads are created, and then trigger a spurious |
| 865 | // work signal. This shouldn't cause any other work signals to be |
| 866 | // triggered. This is a regression test for http://crbug.com/117469. |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 867 | TEST_P(SequencedWorkerPoolTest, SpuriousWorkSignal) { |
| 868 | // This test doesn't apply when tasks are redirected to the TaskScheduler. |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 869 | if (RedirectedToTaskScheduler()) |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 870 | return; |
| 871 | |
[email protected] | 857b600 | 2012-03-12 21:42:13 | [diff] [blame] | 872 | EnsureAllWorkersCreated(); |
[email protected] | 88bbd81 | 2012-03-14 23:17:00 | [diff] [blame] | 873 | int old_has_work_call_count = has_work_call_count(); |
| 874 | pool()->SignalHasWorkForTesting(); |
[email protected] | 857b600 | 2012-03-12 21:42:13 | [diff] [blame] | 875 | // This is inherently racy, but can only produce false positives. |
| 876 | base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); |
[email protected] | 88bbd81 | 2012-03-14 23:17:00 | [diff] [blame] | 877 | EXPECT_EQ(old_has_work_call_count + 1, has_work_call_count()); |
[email protected] | 857b600 | 2012-03-12 21:42:13 | [diff] [blame] | 878 | } |
| 879 | |
fdoray | 2c56f2d | 2016-09-15 21:31:19 | [diff] [blame] | 880 | void VerifyRunsTasksOnCurrentThread( |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 881 | bool redirected_to_task_scheduler, |
fdoray | 2c56f2d | 2016-09-15 21:31:19 | [diff] [blame] | 882 | scoped_refptr<TaskRunner> test_positive_task_runner, |
| 883 | scoped_refptr<TaskRunner> test_negative_task_runner, |
[email protected] | f6f074d0 | 2012-03-30 22:33:46 | [diff] [blame] | 884 | SequencedWorkerPool* pool, |
| 885 | SequencedWorkerPool* unused_pool) { |
Yeol | a89b266 | 2017-07-25 17:09:10 | [diff] [blame] | 886 | EXPECT_TRUE(test_positive_task_runner->RunsTasksInCurrentSequence()); |
| 887 | EXPECT_FALSE(test_negative_task_runner->RunsTasksInCurrentSequence()); |
| 888 | EXPECT_TRUE(pool->RunsTasksInCurrentSequence()); |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 889 | |
| 890 | // Tasks posted to different SequencedWorkerPools may run on the same |
| 891 | // TaskScheduler threads. |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 892 | if (redirected_to_task_scheduler) |
Yeol | a89b266 | 2017-07-25 17:09:10 | [diff] [blame] | 893 | EXPECT_TRUE(unused_pool->RunsTasksInCurrentSequence()); |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 894 | else |
Yeol | a89b266 | 2017-07-25 17:09:10 | [diff] [blame] | 895 | EXPECT_FALSE(unused_pool->RunsTasksInCurrentSequence()); |
[email protected] | f6f074d0 | 2012-03-30 22:33:46 | [diff] [blame] | 896 | } |
| 897 | |
fdoray | 2c56f2d | 2016-09-15 21:31:19 | [diff] [blame] | 898 | // Verify correctness of the RunsTasksOnCurrentThread() method on |
| 899 | // SequencedWorkerPool and on TaskRunners it returns. |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 900 | TEST_P(SequencedWorkerPoolTest, RunsTasksOnCurrentThread) { |
fdoray | 2c56f2d | 2016-09-15 21:31:19 | [diff] [blame] | 901 | const scoped_refptr<SequencedTaskRunner> sequenced_task_runner_1 = |
| 902 | pool()->GetSequencedTaskRunner(SequencedWorkerPool::GetSequenceToken()); |
| 903 | const scoped_refptr<SequencedTaskRunner> sequenced_task_runner_2 = |
| 904 | pool()->GetSequencedTaskRunner(SequencedWorkerPool::GetSequenceToken()); |
| 905 | const scoped_refptr<TaskRunner> unsequenced_task_runner = |
| 906 | pool()->GetTaskRunnerWithShutdownBehavior( |
| 907 | SequencedWorkerPool::BLOCK_SHUTDOWN); |
[email protected] | f6f074d0 | 2012-03-30 22:33:46 | [diff] [blame] | 908 | |
tapted | 012326b | 2015-12-03 04:43:05 | [diff] [blame] | 909 | SequencedWorkerPoolOwner unused_pool_owner(2, "unused_pool"); |
[email protected] | f6f074d0 | 2012-03-30 22:33:46 | [diff] [blame] | 910 | |
Yeol | a89b266 | 2017-07-25 17:09:10 | [diff] [blame] | 911 | EXPECT_FALSE(pool()->RunsTasksInCurrentSequence()); |
| 912 | EXPECT_FALSE(sequenced_task_runner_1->RunsTasksInCurrentSequence()); |
| 913 | EXPECT_FALSE(sequenced_task_runner_2->RunsTasksInCurrentSequence()); |
| 914 | EXPECT_FALSE(unsequenced_task_runner->RunsTasksInCurrentSequence()); |
| 915 | EXPECT_FALSE(unused_pool_owner.pool()->RunsTasksInCurrentSequence()); |
[email protected] | f6f074d0 | 2012-03-30 22:33:46 | [diff] [blame] | 916 | |
fdoray | 2c56f2d | 2016-09-15 21:31:19 | [diff] [blame] | 917 | // From a task posted to |sequenced_task_runner_1|: |
| 918 | // - sequenced_task_runner_1->RunsTasksOnCurrentThread() returns true. |
| 919 | // - sequenced_task_runner_2->RunsTasksOnCurrentThread() returns false. |
| 920 | // - pool()->RunsTasksOnCurrentThread() returns true. |
| 921 | // - unused_pool_owner.pool()->RunsTasksOnCurrentThread() returns false. |
| 922 | sequenced_task_runner_1->PostTask( |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 923 | FROM_HERE, |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 924 | base::BindOnce(&VerifyRunsTasksOnCurrentThread, |
| 925 | RedirectedToTaskScheduler(), sequenced_task_runner_1, |
| 926 | sequenced_task_runner_2, base::RetainedRef(pool()), |
| 927 | base::RetainedRef(unused_pool_owner.pool()))); |
fdoray | 2c56f2d | 2016-09-15 21:31:19 | [diff] [blame] | 928 | // From a task posted to |unsequenced_task_runner|: |
| 929 | // - unsequenced_task_runner->RunsTasksOnCurrentThread() returns true. |
| 930 | // - sequenced_task_runner_1->RunsTasksOnCurrentThread() returns false. |
| 931 | // - pool()->RunsTasksOnCurrentThread() returns true. |
| 932 | // - unused_pool_owner.pool()->RunsTasksOnCurrentThread() returns false. |
| 933 | unsequenced_task_runner->PostTask( |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 934 | FROM_HERE, |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 935 | base::BindOnce(&VerifyRunsTasksOnCurrentThread, |
| 936 | RedirectedToTaskScheduler(), unsequenced_task_runner, |
| 937 | sequenced_task_runner_1, base::RetainedRef(pool()), |
| 938 | base::RetainedRef(unused_pool_owner.pool()))); |
[email protected] | f6f074d0 | 2012-03-30 22:33:46 | [diff] [blame] | 939 | } |
| 940 | |
erikchen | eae82f2 | 2015-02-26 19:37:42 | [diff] [blame] | 941 | // Checks that tasks are destroyed in the right context during shutdown. If a |
| 942 | // task is destroyed while SequencedWorkerPool's global lock is held, |
| 943 | // SequencedWorkerPool might deadlock. |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 944 | TEST_P(SequencedWorkerPoolTest, AvoidsDeadlockOnShutdown) { |
| 945 | // Note: TaskScheduler destroys tasks when it is deleted rather than on |
| 946 | // shutdown. In production, it should never be destroyed. |
| 947 | |
erikchen | eae82f2 | 2015-02-26 19:37:42 | [diff] [blame] | 948 | for (int i = 0; i < 4; ++i) { |
| 949 | scoped_refptr<DestructionDeadlockChecker> checker( |
| 950 | new DestructionDeadlockChecker(pool())); |
| 951 | tracker()->PostRepostingTask(pool(), checker); |
| 952 | } |
| 953 | |
| 954 | // Shutting down the pool should destroy the DestructionDeadlockCheckers, |
| 955 | // which in turn should not deadlock in their destructors. |
| 956 | pool()->Shutdown(); |
| 957 | } |
| 958 | |
erikchen | 19249bcc | 2015-03-13 22:57:37 | [diff] [blame] | 959 | // Similar to the test AvoidsDeadlockOnShutdown, but there are now also |
| 960 | // sequenced, blocking tasks in the queue during shutdown. |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 961 | TEST_P(SequencedWorkerPoolTest, |
erikchen | 19249bcc | 2015-03-13 22:57:37 | [diff] [blame] | 962 | AvoidsDeadlockOnShutdownWithSequencedBlockingTasks) { |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 963 | // This test continuously posts BLOCK_SHUTDOWN tasks |
| 964 | // (PostRepostingBlockingTask). It can't run when tasks are redirected to |
| 965 | // TaskScheduler because TaskScheduler doesn't provide a way to limit the |
| 966 | // number of BLOCK_SHUTDOWN tasks posted during shutdown. |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 967 | if (RedirectedToTaskScheduler()) |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 968 | return; |
| 969 | |
erikchen | 19249bcc | 2015-03-13 22:57:37 | [diff] [blame] | 970 | const std::string sequence_token_name("name"); |
| 971 | for (int i = 0; i < 4; ++i) { |
| 972 | scoped_refptr<DestructionDeadlockChecker> checker( |
| 973 | new DestructionDeadlockChecker(pool())); |
| 974 | tracker()->PostRepostingTask(pool(), checker); |
| 975 | |
| 976 | SequencedWorkerPool::SequenceToken token1 = |
| 977 | pool()->GetNamedSequenceToken(sequence_token_name); |
| 978 | tracker()->PostRepostingBlockingTask(pool(), token1); |
| 979 | } |
| 980 | |
| 981 | // Shutting down the pool should destroy the DestructionDeadlockCheckers, |
| 982 | // which in turn should not deadlock in their destructors. |
| 983 | pool()->Shutdown(); |
| 984 | } |
| 985 | |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 986 | // Verify that FlushForTesting works as intended. |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 987 | TEST_P(SequencedWorkerPoolTest, FlushForTesting) { |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 988 | // Should be fine to call on a new instance. |
| 989 | pool()->FlushForTesting(); |
| 990 | |
| 991 | // Queue up a bunch of work, including a long delayed task and |
| 992 | // a task that produces additional tasks as an artifact. |
fdoray | 940082f | 2017-05-16 19:47:21 | [diff] [blame] | 993 | pool()->PostDelayedTask(FROM_HERE, |
| 994 | base::BindOnce(&TestTracker::FastTask, tracker(), 0), |
| 995 | TimeDelta::FromMinutes(5)); |
sdefresne | 3f731c7 | 2017-05-30 12:52:52 | [diff] [blame] | 996 | pool()->PostWorkerTask(FROM_HERE, |
| 997 | base::BindOnce(&TestTracker::SlowTask, tracker(), 0)); |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 998 | const size_t kNumFastTasks = 20; |
| 999 | for (size_t i = 0; i < kNumFastTasks; i++) { |
sdefresne | 3f731c7 | 2017-05-30 12:52:52 | [diff] [blame] | 1000 | pool()->PostWorkerTask( |
| 1001 | FROM_HERE, base::BindOnce(&TestTracker::FastTask, tracker(), 0)); |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 1002 | } |
sdefresne | 3f731c7 | 2017-05-30 12:52:52 | [diff] [blame] | 1003 | pool()->PostWorkerTask( |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 1004 | FROM_HERE, base::BindOnce(&TestTracker::PostAdditionalTasks, tracker(), 0, |
| 1005 | base::RetainedRef(pool()), true)); |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 1006 | |
| 1007 | // We expect all except the delayed task to have been run. We verify all |
[email protected] | 4f60d80 | 2013-04-18 05:41:23 | [diff] [blame] | 1008 | // closures have been deleted by looking at the refcount of the |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 1009 | // tracker. |
| 1010 | EXPECT_FALSE(tracker()->HasOneRef()); |
| 1011 | pool()->FlushForTesting(); |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 1012 | EXPECT_EQ(1 + kNumFastTasks + 1 + 3, tracker()->GetTasksCompletedCount()); |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 1013 | // TaskScheduler deletes unexecuted delayed tasks as part of ~TaskScheduler() |
| 1014 | // instead of TaskScheduler::FlushForTesting(). |
| 1015 | EXPECT_EQ(!RedirectedToTaskScheduler(), tracker()->HasOneRef()); |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 1016 | |
| 1017 | // Should be fine to call on an idle instance with all threads created, and |
| 1018 | // spamming the method shouldn't deadlock or confuse the class. |
| 1019 | pool()->FlushForTesting(); |
| 1020 | pool()->FlushForTesting(); |
| 1021 | |
| 1022 | // Should be fine to call after shutdown too. |
| 1023 | pool()->Shutdown(); |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 1024 | if (RedirectedToTaskScheduler()) |
| 1025 | TaskScheduler::GetInstance()->Shutdown(); |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 1026 | pool()->FlushForTesting(); |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 1027 | |
| 1028 | // Verify that all tasks are deleted once the SequencedWorkerPool and the |
| 1029 | // TaskScheduler are deleted. |
| 1030 | DeletePool(); |
| 1031 | if (RedirectedToTaskScheduler()) |
| 1032 | DeleteTaskScheduler(); |
| 1033 | EXPECT_TRUE(tracker()->HasOneRef()); |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 1034 | } |
| 1035 | |
gab | a414e99 | 2016-08-01 17:29:50 | [diff] [blame] | 1036 | namespace { |
bauerb | 5d315e4b | 2016-01-07 15:34:08 | [diff] [blame] | 1037 | |
gab | a414e99 | 2016-08-01 17:29:50 | [diff] [blame] | 1038 | void CheckWorkerPoolAndSequenceToken( |
| 1039 | const scoped_refptr<SequencedWorkerPool>& expected_pool, |
| 1040 | SequencedWorkerPool::SequenceToken expected_token) { |
| 1041 | SequencedWorkerPool::SequenceToken token = |
gab | 33a2c41 | 2016-07-28 19:05:07 | [diff] [blame] | 1042 | SequencedWorkerPool::GetSequenceTokenForCurrentThread(); |
gab | a414e99 | 2016-08-01 17:29:50 | [diff] [blame] | 1043 | EXPECT_EQ(expected_token.ToString(), token.ToString()); |
gab | 33a2c41 | 2016-07-28 19:05:07 | [diff] [blame] | 1044 | |
gab | a414e99 | 2016-08-01 17:29:50 | [diff] [blame] | 1045 | scoped_refptr<SequencedWorkerPool> pool = |
| 1046 | SequencedWorkerPool::GetWorkerPoolForCurrentThread(); |
| 1047 | EXPECT_EQ(expected_pool, pool); |
gab | 33a2c41 | 2016-07-28 19:05:07 | [diff] [blame] | 1048 | } |
| 1049 | |
gab | a414e99 | 2016-08-01 17:29:50 | [diff] [blame] | 1050 | } // namespace |
| 1051 | |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 1052 | TEST_P(SequencedWorkerPoolTest, GetWorkerPoolAndSequenceTokenForCurrentThread) { |
| 1053 | // GetSequenceTokenForCurrentThread() and GetWorkerPoolForCurrentThread() |
| 1054 | // respectively return an invalid token and nullptr from a task posted to a |
| 1055 | // SequencedWorkerPool when redirection to TaskScheduler is enabled. These |
| 1056 | // methods are only used from SequencedTaskRunnerHandle and |
| 1057 | // SequenceCheckerImpl which work fine in TaskScheduler. |
fdoray | bca8090 | 2016-09-27 13:41:07 | [diff] [blame] | 1058 | if (RedirectedToTaskScheduler()) |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 1059 | return; |
| 1060 | |
bauerb | 8a40872 | 2015-10-30 09:05:31 | [diff] [blame] | 1061 | EnsureAllWorkersCreated(); |
| 1062 | |
gab | a414e99 | 2016-08-01 17:29:50 | [diff] [blame] | 1063 | // The current thread should have neither a worker pool nor a sequence token. |
| 1064 | SequencedWorkerPool::SequenceToken local_token = |
| 1065 | SequencedWorkerPool::GetSequenceTokenForCurrentThread(); |
| 1066 | scoped_refptr<SequencedWorkerPool> local_pool = |
| 1067 | SequencedWorkerPool::GetWorkerPoolForCurrentThread(); |
| 1068 | EXPECT_FALSE(local_token.IsValid()) << local_token.ToString(); |
| 1069 | EXPECT_FALSE(local_pool); |
bauerb | 8a40872 | 2015-10-30 09:05:31 | [diff] [blame] | 1070 | |
gab | a414e99 | 2016-08-01 17:29:50 | [diff] [blame] | 1071 | SequencedWorkerPool::SequenceToken token1 = pool()->GetSequenceToken(); |
| 1072 | SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken(); |
| 1073 | pool()->PostSequencedWorkerTask( |
| 1074 | token1, FROM_HERE, |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 1075 | base::BindOnce(&CheckWorkerPoolAndSequenceToken, pool(), token1)); |
gab | a414e99 | 2016-08-01 17:29:50 | [diff] [blame] | 1076 | pool()->PostSequencedWorkerTask( |
| 1077 | token2, FROM_HERE, |
tzik | 92b7a42 | 2017-04-11 15:00:44 | [diff] [blame] | 1078 | base::BindOnce(&CheckWorkerPoolAndSequenceToken, pool(), token2)); |
bauerb | 8a40872 | 2015-10-30 09:05:31 | [diff] [blame] | 1079 | |
sdefresne | 3f731c7 | 2017-05-30 12:52:52 | [diff] [blame] | 1080 | pool()->PostWorkerTask( |
| 1081 | FROM_HERE, base::BindOnce(&CheckWorkerPoolAndSequenceToken, pool(), |
| 1082 | SequencedWorkerPool::SequenceToken())); |
bauerb | 8a40872 | 2015-10-30 09:05:31 | [diff] [blame] | 1083 | |
gab | a414e99 | 2016-08-01 17:29:50 | [diff] [blame] | 1084 | pool()->FlushForTesting(); |
bauerb | 8a40872 | 2015-10-30 09:05:31 | [diff] [blame] | 1085 | } |
| 1086 | |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 1087 | TEST_P(SequencedWorkerPoolTest, ShutsDownCleanWithContinueOnShutdown) { |
[email protected] | 4f60d80 | 2013-04-18 05:41:23 | [diff] [blame] | 1088 | scoped_refptr<SequencedTaskRunner> task_runner = |
tapted | 012326b | 2015-12-03 04:43:05 | [diff] [blame] | 1089 | pool()->GetSequencedTaskRunnerWithShutdownBehavior( |
| 1090 | pool()->GetSequenceToken(), |
[email protected] | 4f60d80 | 2013-04-18 05:41:23 | [diff] [blame] | 1091 | base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); |
| 1092 | |
| 1093 | // Upon test exit, should shut down without hanging. |
tapted | 012326b | 2015-12-03 04:43:05 | [diff] [blame] | 1094 | pool()->Shutdown(); |
[email protected] | 4f60d80 | 2013-04-18 05:41:23 | [diff] [blame] | 1095 | } |
| 1096 | |
fdoray | 37e79479 | 2016-09-16 23:19:50 | [diff] [blame] | 1097 | INSTANTIATE_TEST_CASE_P( |
| 1098 | NoRedirection, |
| 1099 | SequencedWorkerPoolTest, |
| 1100 | ::testing::Values(SequencedWorkerPoolRedirection::NONE)); |
| 1101 | INSTANTIATE_TEST_CASE_P( |
| 1102 | RedirectionToTaskScheduler, |
| 1103 | SequencedWorkerPoolTest, |
| 1104 | ::testing::Values(SequencedWorkerPoolRedirection::TO_TASK_SCHEDULER)); |
| 1105 | |
[email protected] | 506fc23 | 2012-02-29 01:33:03 | [diff] [blame] | 1106 | class SequencedWorkerPoolTaskRunnerTestDelegate { |
| 1107 | public: |
| 1108 | SequencedWorkerPoolTaskRunnerTestDelegate() {} |
| 1109 | |
| 1110 | ~SequencedWorkerPoolTaskRunnerTestDelegate() {} |
| 1111 | |
| 1112 | void StartTaskRunner() { |
[email protected] | 71b18fb | 2012-03-06 14:17:34 | [diff] [blame] | 1113 | pool_owner_.reset( |
| 1114 | new SequencedWorkerPoolOwner(10, "SequencedWorkerPoolTaskRunnerTest")); |
[email protected] | 506fc23 | 2012-02-29 01:33:03 | [diff] [blame] | 1115 | } |
| 1116 | |
| 1117 | scoped_refptr<SequencedWorkerPool> GetTaskRunner() { |
[email protected] | 71b18fb | 2012-03-06 14:17:34 | [diff] [blame] | 1118 | return pool_owner_->pool(); |
[email protected] | 506fc23 | 2012-02-29 01:33:03 | [diff] [blame] | 1119 | } |
| 1120 | |
| 1121 | void StopTaskRunner() { |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 1122 | // Make sure all tasks are run before shutting down. Delayed tasks are |
| 1123 | // not run, they're simply deleted. |
[email protected] | 113d2ac | 2012-10-02 08:31:57 | [diff] [blame] | 1124 | pool_owner_->pool()->FlushForTesting(); |
[email protected] | 71b18fb | 2012-03-06 14:17:34 | [diff] [blame] | 1125 | pool_owner_->pool()->Shutdown(); |
| 1126 | // Don't reset |pool_owner_| here, as the test may still hold a |
| 1127 | // reference to the pool. |
[email protected] | 506fc23 | 2012-02-29 01:33:03 | [diff] [blame] | 1128 | } |
| 1129 | |
[email protected] | 506fc23 | 2012-02-29 01:33:03 | [diff] [blame] | 1130 | private: |
[email protected] | 71b18fb | 2012-03-06 14:17:34 | [diff] [blame] | 1131 | MessageLoop message_loop_; |
dcheng | 093de9b | 2016-04-04 21:25:51 | [diff] [blame] | 1132 | std::unique_ptr<SequencedWorkerPoolOwner> pool_owner_; |
[email protected] | 506fc23 | 2012-02-29 01:33:03 | [diff] [blame] | 1133 | }; |
| 1134 | |
| 1135 | INSTANTIATE_TYPED_TEST_CASE_P( |
| 1136 | SequencedWorkerPool, TaskRunnerTest, |
| 1137 | SequencedWorkerPoolTaskRunnerTestDelegate); |
dcastagna | ef1312d | 2015-07-24 23:28:11 | [diff] [blame] | 1138 | INSTANTIATE_TYPED_TEST_CASE_P(SequencedWorkerPool, TaskRunnerAffinityTest, |
| 1139 | SequencedWorkerPoolTaskRunnerTestDelegate); |
[email protected] | 506fc23 | 2012-02-29 01:33:03 | [diff] [blame] | 1140 | |
[email protected] | 497ec46 | 2012-04-11 22:42:29 | [diff] [blame] | 1141 | class SequencedWorkerPoolTaskRunnerWithShutdownBehaviorTestDelegate { |
| 1142 | public: |
| 1143 | SequencedWorkerPoolTaskRunnerWithShutdownBehaviorTestDelegate() {} |
| 1144 | |
| 1145 | ~SequencedWorkerPoolTaskRunnerWithShutdownBehaviorTestDelegate() { |
| 1146 | } |
| 1147 | |
| 1148 | void StartTaskRunner() { |
| 1149 | pool_owner_.reset( |
| 1150 | new SequencedWorkerPoolOwner(10, "SequencedWorkerPoolTaskRunnerTest")); |
| 1151 | task_runner_ = pool_owner_->pool()->GetTaskRunnerWithShutdownBehavior( |
| 1152 | SequencedWorkerPool::BLOCK_SHUTDOWN); |
| 1153 | } |
| 1154 | |
| 1155 | scoped_refptr<TaskRunner> GetTaskRunner() { |
| 1156 | return task_runner_; |
| 1157 | } |
| 1158 | |
| 1159 | void StopTaskRunner() { |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 1160 | // Make sure all tasks are run before shutting down. Delayed tasks are |
| 1161 | // not run, they're simply deleted. |
[email protected] | 497ec46 | 2012-04-11 22:42:29 | [diff] [blame] | 1162 | pool_owner_->pool()->FlushForTesting(); |
| 1163 | pool_owner_->pool()->Shutdown(); |
| 1164 | // Don't reset |pool_owner_| here, as the test may still hold a |
| 1165 | // reference to the pool. |
| 1166 | } |
| 1167 | |
[email protected] | 497ec46 | 2012-04-11 22:42:29 | [diff] [blame] | 1168 | private: |
| 1169 | MessageLoop message_loop_; |
dcheng | 093de9b | 2016-04-04 21:25:51 | [diff] [blame] | 1170 | std::unique_ptr<SequencedWorkerPoolOwner> pool_owner_; |
[email protected] | 497ec46 | 2012-04-11 22:42:29 | [diff] [blame] | 1171 | scoped_refptr<TaskRunner> task_runner_; |
| 1172 | }; |
| 1173 | |
| 1174 | INSTANTIATE_TYPED_TEST_CASE_P( |
| 1175 | SequencedWorkerPoolTaskRunner, TaskRunnerTest, |
| 1176 | SequencedWorkerPoolTaskRunnerWithShutdownBehaviorTestDelegate); |
dcastagna | ef1312d | 2015-07-24 23:28:11 | [diff] [blame] | 1177 | INSTANTIATE_TYPED_TEST_CASE_P( |
| 1178 | SequencedWorkerPoolTaskRunner, TaskRunnerAffinityTest, |
| 1179 | SequencedWorkerPoolTaskRunnerWithShutdownBehaviorTestDelegate); |
[email protected] | 497ec46 | 2012-04-11 22:42:29 | [diff] [blame] | 1180 | |
[email protected] | 89993aee | 2012-04-11 08:10:11 | [diff] [blame] | 1181 | class SequencedWorkerPoolSequencedTaskRunnerTestDelegate { |
| 1182 | public: |
| 1183 | SequencedWorkerPoolSequencedTaskRunnerTestDelegate() {} |
| 1184 | |
| 1185 | ~SequencedWorkerPoolSequencedTaskRunnerTestDelegate() { |
| 1186 | } |
| 1187 | |
| 1188 | void StartTaskRunner() { |
| 1189 | pool_owner_.reset(new SequencedWorkerPoolOwner( |
| 1190 | 10, "SequencedWorkerPoolSequencedTaskRunnerTest")); |
| 1191 | task_runner_ = pool_owner_->pool()->GetSequencedTaskRunner( |
| 1192 | pool_owner_->pool()->GetSequenceToken()); |
| 1193 | } |
| 1194 | |
| 1195 | scoped_refptr<SequencedTaskRunner> GetTaskRunner() { |
| 1196 | return task_runner_; |
| 1197 | } |
| 1198 | |
| 1199 | void StopTaskRunner() { |
[email protected] | 13ecb5e9 | 2013-03-07 01:35:37 | [diff] [blame] | 1200 | // Make sure all tasks are run before shutting down. Delayed tasks are |
| 1201 | // not run, they're simply deleted. |
[email protected] | 89993aee | 2012-04-11 08:10:11 | [diff] [blame] | 1202 | pool_owner_->pool()->FlushForTesting(); |
| 1203 | pool_owner_->pool()->Shutdown(); |
| 1204 | // Don't reset |pool_owner_| here, as the test may still hold a |
| 1205 | // reference to the pool. |
| 1206 | } |
| 1207 | |
[email protected] | 89993aee | 2012-04-11 08:10:11 | [diff] [blame] | 1208 | private: |
| 1209 | MessageLoop message_loop_; |
dcheng | 093de9b | 2016-04-04 21:25:51 | [diff] [blame] | 1210 | std::unique_ptr<SequencedWorkerPoolOwner> pool_owner_; |
[email protected] | 89993aee | 2012-04-11 08:10:11 | [diff] [blame] | 1211 | scoped_refptr<SequencedTaskRunner> task_runner_; |
| 1212 | }; |
| 1213 | |
| 1214 | INSTANTIATE_TYPED_TEST_CASE_P( |
| 1215 | SequencedWorkerPoolSequencedTaskRunner, TaskRunnerTest, |
| 1216 | SequencedWorkerPoolSequencedTaskRunnerTestDelegate); |
dcastagna | ef1312d | 2015-07-24 23:28:11 | [diff] [blame] | 1217 | INSTANTIATE_TYPED_TEST_CASE_P( |
| 1218 | SequencedWorkerPoolSequencedTaskRunner, TaskRunnerAffinityTest, |
| 1219 | SequencedWorkerPoolSequencedTaskRunnerTestDelegate); |
[email protected] | 89993aee | 2012-04-11 08:10:11 | [diff] [blame] | 1220 | |
| 1221 | INSTANTIATE_TYPED_TEST_CASE_P( |
| 1222 | SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, |
| 1223 | SequencedWorkerPoolSequencedTaskRunnerTestDelegate); |
dcastagna | 29e7fc6 | 2015-07-31 23:20:06 | [diff] [blame] | 1224 | INSTANTIATE_TYPED_TEST_CASE_P( |
| 1225 | SequencedWorkerPoolSequencedTaskRunner, |
| 1226 | SequencedTaskRunnerDelayedTest, |
| 1227 | SequencedWorkerPoolSequencedTaskRunnerTestDelegate); |
[email protected] | 89993aee | 2012-04-11 08:10:11 | [diff] [blame] | 1228 | |
[email protected] | 506fc23 | 2012-02-29 01:33:03 | [diff] [blame] | 1229 | } // namespace |
| 1230 | |
[email protected] | 098def2 | 2012-01-01 05:42:34 | [diff] [blame] | 1231 | } // namespace base |