Chromium Code Reviews| 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/scheduler_thread_pool.h" | 5 #include "base/task_scheduler/scheduler_thread_pool.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <unordered_set> | 10 #include <unordered_set> |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
| 25 | 25 |
| 26 namespace base { | 26 namespace base { |
| 27 namespace internal { | 27 namespace internal { |
| 28 namespace { | 28 namespace { |
| 29 | 29 |
| 30 const size_t kNumThreadsInThreadPool = 4; | 30 const size_t kNumThreadsInThreadPool = 4; |
| 31 const size_t kNumThreadsPostingTasks = 4; | 31 const size_t kNumThreadsPostingTasks = 4; |
| 32 const size_t kNumTasksPostedPerThread = 150; | 32 const size_t kNumTasksPostedPerThread = 150; |
| 33 | 33 |
| 34 class TaskSchedulerThreadPoolTest : public testing::Test { | 34 class TaskSchedulerThreadPoolTest |
| 35 : public testing::TestWithParam<ExecutionMode> { | |
| 35 protected: | 36 protected: |
| 36 TaskSchedulerThreadPoolTest() = default; | 37 TaskSchedulerThreadPoolTest() = default; |
| 37 | 38 |
| 38 void SetUp() override { | 39 void SetUp() override { |
| 39 thread_pool_ = SchedulerThreadPool::CreateThreadPool( | 40 thread_pool_ = SchedulerThreadPool::CreateThreadPool( |
| 40 ThreadPriority::NORMAL, kNumThreadsInThreadPool, | 41 ThreadPriority::NORMAL, kNumThreadsInThreadPool, |
| 41 Bind(&TaskSchedulerThreadPoolTest::RanTaskFromSequenceCallback, | 42 Bind(&TaskSchedulerThreadPoolTest::RanTaskFromSequenceCallback, |
| 42 Unretained(this)), | 43 Unretained(this)), |
| 43 &task_tracker_); | 44 &task_tracker_); |
| 44 ASSERT_TRUE(thread_pool_); | 45 ASSERT_TRUE(thread_pool_); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 64 } | 65 } |
| 65 } | 66 } |
| 66 | 67 |
| 67 TaskTracker task_tracker_; | 68 TaskTracker task_tracker_; |
| 68 | 69 |
| 69 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerThreadPoolTest); | 70 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerThreadPoolTest); |
| 70 }; | 71 }; |
| 71 | 72 |
| 72 class TaskFactory { | 73 class TaskFactory { |
| 73 public: | 74 public: |
| 74 TaskFactory() : cv_(&lock_) {} | 75 // Constructs a TaskFactory that posts tasks through |task_runner|. |
| 76 // |execution_mode| is the execution mode of |task_runner|. | |
| 77 TaskFactory(scoped_refptr<TaskRunner> task_runner, | |
|
robliao
2016/04/04 18:45:50
I wonder if there's a way we can extract this out
fdoray
2016/04/04 19:41:18
I changed the code to avoid relying on the caller
| |
| 78 ExecutionMode execution_mode) | |
| 79 : cv_(&lock_), | |
| 80 task_runner_(std::move(task_runner)), | |
| 81 execution_mode_(execution_mode) {} | |
| 75 | 82 |
| 76 // Posts a task through |task_runner|. If |post_nested_task| is true, the task | 83 // Posts a task. If |post_nested_task| is true, the task will post a new task |
| 77 // will post a new task through |task_runner| when it runs. If |event| is set, | 84 // when it runs. If |event| is set, the task will block until it is signaled. |
| 78 // the task will block until it is signaled. | 85 void PostTask(bool post_nested_task, WaitableEvent* event) { |
| 79 void PostTask(scoped_refptr<TaskRunner> task_runner, | |
| 80 bool post_nested_task, | |
| 81 WaitableEvent* event) { | |
| 82 AutoLock auto_lock(lock_); | 86 AutoLock auto_lock(lock_); |
| 83 task_runner->PostTask( | 87 task_runner_->PostTask( |
| 84 FROM_HERE, Bind(&TaskFactory::RunTaskCallback, Unretained(this), | 88 FROM_HERE, |
| 85 num_created_tasks_++, task_runner, post_nested_task, | 89 Bind(&TaskFactory::RunTaskCallback, Unretained(this), |
| 86 Unretained(event))); | 90 num_created_tasks_++, post_nested_task, Unretained(event))); |
| 87 } | 91 } |
| 88 | 92 |
| 89 // Waits for all tasks posted by PostTask() to start running. It is not | 93 // Waits for all tasks posted by PostTask() to start running. It is not |
| 90 // guaranteed that the tasks have completed their execution when this returns. | 94 // guaranteed that the tasks have completed their execution when this returns. |
| 91 void WaitForAllTasksToRun() const { | 95 void WaitForAllTasksToRun() const { |
| 92 AutoLock auto_lock(lock_); | 96 AutoLock auto_lock(lock_); |
| 93 while (run_tasks_.size() < num_created_tasks_) | 97 while (run_tasks_.size() < num_created_tasks_) |
| 94 cv_.Wait(); | 98 cv_.Wait(); |
| 95 } | 99 } |
| 96 | 100 |
| 97 size_t NumRunTasks() const { | 101 size_t NumRunTasks() const { |
| 98 AutoLock auto_lock(lock_); | 102 AutoLock auto_lock(lock_); |
| 99 return run_tasks_.size(); | 103 return run_tasks_.size(); |
| 100 } | 104 } |
| 101 | 105 |
| 102 private: | 106 private: |
| 103 void RunTaskCallback(size_t task_index, | 107 void RunTaskCallback(size_t task_index, |
| 104 scoped_refptr<TaskRunner> task_runner, | |
| 105 bool post_nested_task, | 108 bool post_nested_task, |
| 106 WaitableEvent* event) { | 109 WaitableEvent* event) { |
| 107 if (post_nested_task) | 110 if (post_nested_task) |
| 108 PostTask(task_runner, false, nullptr); | 111 PostTask(false, nullptr); |
| 109 | 112 |
| 110 EXPECT_TRUE(task_runner->RunsTasksOnCurrentThread()); | 113 EXPECT_TRUE(task_runner_->RunsTasksOnCurrentThread()); |
| 111 | 114 |
| 112 { | 115 { |
| 113 AutoLock auto_lock(lock_); | 116 AutoLock auto_lock(lock_); |
| 114 | 117 |
| 118 if (execution_mode_ == ExecutionMode::SEQUENCED && | |
| 119 task_index != run_tasks_.size()) { | |
| 120 ADD_FAILURE() << "A SEQUENCED task didn't run in the expected order."; | |
| 121 } | |
| 122 | |
| 115 if (run_tasks_.find(task_index) != run_tasks_.end()) | 123 if (run_tasks_.find(task_index) != run_tasks_.end()) |
| 116 ADD_FAILURE() << "A task ran more than once."; | 124 ADD_FAILURE() << "A task ran more than once."; |
| 117 run_tasks_.insert(task_index); | 125 run_tasks_.insert(task_index); |
| 118 | 126 |
| 119 cv_.Signal(); | 127 cv_.Signal(); |
| 120 } | 128 } |
| 121 | 129 |
| 122 if (event) | 130 if (event) |
| 123 event->Wait(); | 131 event->Wait(); |
| 124 } | 132 } |
| 125 | 133 |
| 126 // Synchronizes access to all members below. | 134 // Synchronizes access to all members below. |
| 127 mutable Lock lock_; | 135 mutable Lock lock_; |
| 128 | 136 |
| 129 // Condition variable signaled when a task runs. | 137 // Condition variable signaled when a task runs. |
| 130 mutable ConditionVariable cv_; | 138 mutable ConditionVariable cv_; |
| 131 | 139 |
| 140 // Task runner through which this factory posts tasks. | |
| 141 const scoped_refptr<TaskRunner> task_runner_; | |
| 142 | |
| 143 // Execution mode of |task_runner_|. | |
| 144 const ExecutionMode execution_mode_; | |
| 145 | |
| 132 // Number of tasks posted by PostTask(). | 146 // Number of tasks posted by PostTask(). |
| 133 size_t num_created_tasks_ = 0; | 147 size_t num_created_tasks_ = 0; |
| 134 | 148 |
| 135 // Indexes of tasks that ran. | 149 // Indexes of tasks that ran. |
| 136 std::unordered_set<size_t> run_tasks_; | 150 std::unordered_set<size_t> run_tasks_; |
| 137 | 151 |
| 138 DISALLOW_COPY_AND_ASSIGN(TaskFactory); | 152 DISALLOW_COPY_AND_ASSIGN(TaskFactory); |
| 139 }; | 153 }; |
| 140 | 154 |
| 141 class ThreadPostingTasks : public SimpleThread { | 155 class ThreadPostingTasks : public SimpleThread { |
| 142 public: | 156 public: |
| 143 // Constructs a thread that posts tasks to |thread_pool| through an | 157 // Constructs a thread that posts tasks to |thread_pool| through an |
| 144 // |execution_mode| task runner. If |wait_for_all_threads_idle| is true, the | 158 // |execution_mode| task runner. If |wait_for_all_threads_idle| is true, the |
| 145 // thread wait until all worker threads in |thread_pool| are idle before | 159 // thread wait until all worker threads in |thread_pool| are idle before |
| 146 // posting a new task. If |post_nested_task| is true, each task posted by this | 160 // posting a new task. If |post_nested_task| is true, each task posted by this |
| 147 // thread posts another task when it runs. | 161 // thread posts another task when it runs. |
| 148 ThreadPostingTasks(SchedulerThreadPool* thread_pool, | 162 ThreadPostingTasks(SchedulerThreadPool* thread_pool, |
| 149 ExecutionMode execution_mode, | 163 ExecutionMode execution_mode, |
| 150 bool wait_for_all_threads_idle, | 164 bool wait_for_all_threads_idle, |
| 151 bool post_nested_task) | 165 bool post_nested_task) |
| 152 : SimpleThread("ThreadPostingTasks"), | 166 : SimpleThread("ThreadPostingTasks"), |
| 153 thread_pool_(thread_pool), | 167 thread_pool_(thread_pool), |
| 154 task_runner_(thread_pool_->CreateTaskRunnerWithTraits(TaskTraits(), | 168 task_runner_(thread_pool_->CreateTaskRunnerWithTraits(TaskTraits(), |
| 155 execution_mode)), | 169 execution_mode)), |
| 156 wait_for_all_threads_idle_(wait_for_all_threads_idle), | 170 wait_for_all_threads_idle_(wait_for_all_threads_idle), |
| 157 post_nested_task_(post_nested_task) {} | 171 post_nested_task_(post_nested_task), |
| 172 factory_(task_runner_, execution_mode) {} | |
| 158 | 173 |
| 159 const TaskFactory* factory() const { return &factory_; } | 174 const TaskFactory* factory() const { return &factory_; } |
| 160 | 175 |
| 161 private: | 176 private: |
| 162 void Run() override { | 177 void Run() override { |
| 163 EXPECT_FALSE(task_runner_->RunsTasksOnCurrentThread()); | 178 EXPECT_FALSE(task_runner_->RunsTasksOnCurrentThread()); |
| 164 | 179 |
| 165 for (size_t i = 0; i < kNumTasksPostedPerThread; ++i) { | 180 for (size_t i = 0; i < kNumTasksPostedPerThread; ++i) { |
| 166 if (wait_for_all_threads_idle_) | 181 if (wait_for_all_threads_idle_) |
| 167 thread_pool_->WaitForAllWorkerThreadsIdleForTesting(); | 182 thread_pool_->WaitForAllWorkerThreadsIdleForTesting(); |
| 168 factory_.PostTask(task_runner_, post_nested_task_, nullptr); | 183 factory_.PostTask(post_nested_task_, nullptr); |
| 169 } | 184 } |
| 170 } | 185 } |
| 171 | 186 |
| 172 SchedulerThreadPool* const thread_pool_; | 187 SchedulerThreadPool* const thread_pool_; |
| 173 scoped_refptr<TaskRunner> task_runner_; | 188 scoped_refptr<TaskRunner> task_runner_; |
| 174 const bool wait_for_all_threads_idle_; | 189 const bool wait_for_all_threads_idle_; |
| 175 const bool post_nested_task_; | 190 const bool post_nested_task_; |
| 176 TaskFactory factory_; | 191 TaskFactory factory_; |
| 177 | 192 |
| 178 DISALLOW_COPY_AND_ASSIGN(ThreadPostingTasks); | 193 DISALLOW_COPY_AND_ASSIGN(ThreadPostingTasks); |
| 179 }; | 194 }; |
| 180 | 195 |
| 181 TEST_F(TaskSchedulerThreadPoolTest, PostParallelTasks) { | 196 TEST_P(TaskSchedulerThreadPoolTest, PostTasks) { |
| 182 // Create threads to post tasks to PARALLEL TaskRunners. | 197 // Create threads to post tasks. |
| 183 std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks; | 198 std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks; |
| 184 for (size_t j = 0; j < kNumThreadsPostingTasks; ++j) { | 199 for (size_t j = 0; j < kNumThreadsPostingTasks; ++j) { |
| 185 threads_posting_tasks.push_back(WrapUnique(new ThreadPostingTasks( | 200 threads_posting_tasks.push_back(WrapUnique(new ThreadPostingTasks( |
| 186 thread_pool_.get(), ExecutionMode::PARALLEL, false, false))); | 201 thread_pool_.get(), ExecutionMode::PARALLEL, false, false))); |
|
robliao
2016/04/04 18:45:50
Should PARALLEL be parameterized? All of the tests
fdoray
2016/04/04 19:41:18
Done.
| |
| 187 threads_posting_tasks.back()->Start(); | 202 threads_posting_tasks.back()->Start(); |
| 188 } | 203 } |
| 189 | 204 |
| 190 // Wait for all tasks to run. | 205 // Wait for all tasks to run. |
| 191 for (const auto& thread_posting_tasks : threads_posting_tasks) { | 206 for (const auto& thread_posting_tasks : threads_posting_tasks) { |
| 192 thread_posting_tasks->Join(); | 207 thread_posting_tasks->Join(); |
| 193 thread_posting_tasks->factory()->WaitForAllTasksToRun(); | 208 thread_posting_tasks->factory()->WaitForAllTasksToRun(); |
| 194 EXPECT_EQ(kNumTasksPostedPerThread, | 209 EXPECT_EQ(kNumTasksPostedPerThread, |
| 195 thread_posting_tasks->factory()->NumRunTasks()); | 210 thread_posting_tasks->factory()->NumRunTasks()); |
| 196 } | 211 } |
| 197 } | 212 } |
| 198 | 213 |
| 199 TEST_F(TaskSchedulerThreadPoolTest, PostParallelTasksWaitAllThreadsIdle) { | 214 TEST_P(TaskSchedulerThreadPoolTest, PostTasksWaitAllThreadsIdle) { |
| 200 // Create threads to post tasks to PARALLEL TaskRunners. To verify that | 215 // Create threads to post tasks. To verify that worker threads can sleep and |
| 201 // worker threads can sleep and be woken up when new tasks are posted, wait | 216 // be woken up when new tasks are posted, wait for all threads to become idle |
| 202 // for all threads to become idle before posting a new task. | 217 // before posting a new task. |
| 203 std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks; | 218 std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks; |
| 204 for (size_t j = 0; j < kNumThreadsPostingTasks; ++j) { | 219 for (size_t j = 0; j < kNumThreadsPostingTasks; ++j) { |
| 205 threads_posting_tasks.push_back(WrapUnique(new ThreadPostingTasks( | 220 threads_posting_tasks.push_back(WrapUnique(new ThreadPostingTasks( |
| 206 thread_pool_.get(), ExecutionMode::PARALLEL, true, false))); | 221 thread_pool_.get(), ExecutionMode::PARALLEL, true, false))); |
| 207 threads_posting_tasks.back()->Start(); | 222 threads_posting_tasks.back()->Start(); |
| 208 } | 223 } |
| 209 | 224 |
| 210 // Wait for all tasks to run. | 225 // Wait for all tasks to run. |
| 211 for (const auto& thread_posting_tasks : threads_posting_tasks) { | 226 for (const auto& thread_posting_tasks : threads_posting_tasks) { |
| 212 thread_posting_tasks->Join(); | 227 thread_posting_tasks->Join(); |
| 213 thread_posting_tasks->factory()->WaitForAllTasksToRun(); | 228 thread_posting_tasks->factory()->WaitForAllTasksToRun(); |
| 214 EXPECT_EQ(kNumTasksPostedPerThread, | 229 EXPECT_EQ(kNumTasksPostedPerThread, |
| 215 thread_posting_tasks->factory()->NumRunTasks()); | 230 thread_posting_tasks->factory()->NumRunTasks()); |
| 216 } | 231 } |
| 217 } | 232 } |
| 218 | 233 |
| 219 TEST_F(TaskSchedulerThreadPoolTest, NestedPostParallelTasks) { | 234 TEST_P(TaskSchedulerThreadPoolTest, NestedPostTasks) { |
| 220 // Create threads to post tasks to PARALLEL TaskRunners. Each task posted by | 235 // Create threads to post tasks. Each task posted by these threads will post |
| 221 // these threads will post another task when it runs. | 236 // another task when it runs. |
| 222 std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks; | 237 std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks; |
| 223 for (size_t j = 0; j < kNumThreadsPostingTasks; ++j) { | 238 for (size_t j = 0; j < kNumThreadsPostingTasks; ++j) { |
| 224 threads_posting_tasks.push_back(WrapUnique(new ThreadPostingTasks( | 239 threads_posting_tasks.push_back(WrapUnique(new ThreadPostingTasks( |
| 225 thread_pool_.get(), ExecutionMode::PARALLEL, false, true))); | 240 thread_pool_.get(), ExecutionMode::PARALLEL, false, true))); |
| 226 threads_posting_tasks.back()->Start(); | 241 threads_posting_tasks.back()->Start(); |
| 227 } | 242 } |
| 228 | 243 |
| 229 // Wait for all tasks to run. | 244 // Wait for all tasks to run. |
| 230 for (const auto& thread_posting_tasks : threads_posting_tasks) { | 245 for (const auto& thread_posting_tasks : threads_posting_tasks) { |
| 231 thread_posting_tasks->Join(); | 246 thread_posting_tasks->Join(); |
| 232 thread_posting_tasks->factory()->WaitForAllTasksToRun(); | 247 thread_posting_tasks->factory()->WaitForAllTasksToRun(); |
| 233 EXPECT_EQ(2 * kNumTasksPostedPerThread, | 248 EXPECT_EQ(2 * kNumTasksPostedPerThread, |
| 234 thread_posting_tasks->factory()->NumRunTasks()); | 249 thread_posting_tasks->factory()->NumRunTasks()); |
| 235 } | 250 } |
| 236 | 251 |
| 237 // Wait until all worker threads are idle to be sure that no task accesses | 252 // Wait until all worker threads are idle to be sure that no task accesses |
| 238 // its TaskFactory after |thread_posting_tasks| is destroyed. | 253 // its TaskFactory after |thread_posting_tasks| is destroyed. |
| 239 thread_pool_->WaitForAllWorkerThreadsIdleForTesting(); | 254 thread_pool_->WaitForAllWorkerThreadsIdleForTesting(); |
| 240 } | 255 } |
| 241 | 256 |
| 242 TEST_F(TaskSchedulerThreadPoolTest, PostParallelTasksWithOneAvailableThread) { | 257 TEST_P(TaskSchedulerThreadPoolTest, PostTasksWithOneAvailableThread) { |
| 243 TaskFactory factory; | |
| 244 | |
| 245 // Post tasks to keep all threads busy except one until |event| is signaled. | 258 // Post tasks to keep all threads busy except one until |event| is signaled. |
| 259 // Use different factories so that tasks are added to different sequences when | |
| 260 // the execution mode is SEQUENCED. | |
| 246 WaitableEvent event(true, false); | 261 WaitableEvent event(true, false); |
| 247 auto task_runner = thread_pool_->CreateTaskRunnerWithTraits( | 262 std::vector<scoped_ptr<TaskFactory>> factories; |
| 248 TaskTraits(), ExecutionMode::PARALLEL); | 263 for (size_t i = 0; i < (kNumThreadsInThreadPool - 1); ++i) { |
| 249 for (size_t i = 0; i < (kNumThreadsInThreadPool - 1); ++i) | 264 factories.push_back(make_scoped_ptr(new TaskFactory( |
| 250 factory.PostTask(task_runner, false, &event); | 265 thread_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()), |
| 251 factory.WaitForAllTasksToRun(); | 266 GetParam()))); |
| 267 factories.back()->PostTask(false, &event); | |
| 268 factories.back()->WaitForAllTasksToRun(); | |
| 269 } | |
| 252 | 270 |
| 253 // Post |kNumTasksPostedPerThread| tasks that should all run despite the fact | 271 // Post |kNumTasksPostedPerThread| tasks that should all run despite the fact |
| 254 // that only one thread in |thread_pool_| isn't busy. | 272 // that only one thread in |thread_pool_| isn't busy. |
| 273 factories.push_back(make_scoped_ptr(new TaskFactory( | |
|
robliao
2016/04/04 18:45:50
Should this really be a part of |factories| or doe
fdoray
2016/04/04 19:41:18
Done.
| |
| 274 thread_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()), | |
| 275 GetParam()))); | |
| 255 for (size_t i = 0; i < kNumTasksPostedPerThread; ++i) | 276 for (size_t i = 0; i < kNumTasksPostedPerThread; ++i) |
| 256 factory.PostTask(task_runner, false, nullptr); | 277 factories.back()->PostTask(false, nullptr); |
| 257 factory.WaitForAllTasksToRun(); | 278 factories.back()->WaitForAllTasksToRun(); |
| 258 | 279 |
| 259 // Release tasks waiting on |event|. | 280 // Release tasks waiting on |event|. |
| 260 event.Signal(); | 281 event.Signal(); |
| 261 | 282 |
| 262 // Wait until all worker threads are idle to be sure that no task accesses | 283 // Wait until all worker threads are idle to be sure that no task accesses |
| 263 // its TaskFactory after |factory| is destroyed. | 284 // its TaskFactory after |factories| is destroyed. |
| 264 thread_pool_->WaitForAllWorkerThreadsIdleForTesting(); | 285 thread_pool_->WaitForAllWorkerThreadsIdleForTesting(); |
| 265 } | 286 } |
| 266 | 287 |
| 267 TEST_F(TaskSchedulerThreadPoolTest, Saturate) { | 288 TEST_P(TaskSchedulerThreadPoolTest, Saturate) { |
| 268 TaskFactory factory; | |
| 269 | |
| 270 // Verify that it is possible to have |kNumThreadsInThreadPool| tasks running | 289 // Verify that it is possible to have |kNumThreadsInThreadPool| tasks running |
| 271 // simultaneously. | 290 // simultaneously. Use different factories so that tasks are added to |
| 291 // different sequences when the execution mode is SEQUENCED. | |
| 272 WaitableEvent event(true, false); | 292 WaitableEvent event(true, false); |
| 273 auto task_runner = thread_pool_->CreateTaskRunnerWithTraits( | 293 std::vector<scoped_ptr<TaskFactory>> factories; |
| 274 TaskTraits(), ExecutionMode::PARALLEL); | 294 for (size_t i = 0; i < kNumThreadsInThreadPool; ++i) { |
| 275 for (size_t i = 0; i < kNumThreadsInThreadPool; ++i) | 295 factories.push_back(make_scoped_ptr(new TaskFactory( |
| 276 factory.PostTask(task_runner, false, &event); | 296 thread_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()), |
| 277 factory.WaitForAllTasksToRun(); | 297 GetParam()))); |
| 298 factories.back()->PostTask(false, &event); | |
| 299 factories.back()->WaitForAllTasksToRun(); | |
| 300 } | |
| 278 | 301 |
| 279 // Release tasks waiting on |event|. | 302 // Release tasks waiting on |event|. |
| 280 event.Signal(); | 303 event.Signal(); |
| 281 | 304 |
| 282 // Wait until all worker threads are idle to be sure that no task accesses | 305 // Wait until all worker threads are idle to be sure that no task accesses |
| 283 // its TaskFactory after |factory| is destroyed. | 306 // its TaskFactory after |factories| is destroyed. |
| 284 thread_pool_->WaitForAllWorkerThreadsIdleForTesting(); | 307 thread_pool_->WaitForAllWorkerThreadsIdleForTesting(); |
| 285 } | 308 } |
| 286 | 309 |
| 310 INSTANTIATE_TEST_CASE_P(Parallel, | |
| 311 TaskSchedulerThreadPoolTest, | |
| 312 ::testing::Values(ExecutionMode::PARALLEL)); | |
| 313 INSTANTIATE_TEST_CASE_P(Sequenced, | |
| 314 TaskSchedulerThreadPoolTest, | |
| 315 ::testing::Values(ExecutionMode::SEQUENCED)); | |
| 316 | |
| 287 // Checks that when PostTaskHelper is called with an empty sequence, the task | 317 // Checks that when PostTaskHelper is called with an empty sequence, the task |
| 288 // is added to the sequence and the sequence is added to the priority queue. | 318 // is added to the sequence and the sequence is added to the priority queue. |
| 289 TEST(TaskSchedulerPostTaskHelperTest, PostTaskInEmptySequence) { | 319 TEST(TaskSchedulerPostTaskHelperTest, PostTaskInEmptySequence) { |
| 290 std::unique_ptr<Task> task( | 320 std::unique_ptr<Task> task( |
| 291 new Task(FROM_HERE, Bind(&DoNothing), TaskTraits())); | 321 new Task(FROM_HERE, Bind(&DoNothing), TaskTraits())); |
| 292 const Task* task_raw = task.get(); | 322 const Task* task_raw = task.get(); |
| 293 scoped_refptr<Sequence> sequence(new Sequence); | 323 scoped_refptr<Sequence> sequence(new Sequence); |
| 294 PriorityQueue priority_queue(Bind(&DoNothing)); | 324 PriorityQueue priority_queue(Bind(&DoNothing)); |
| 295 TaskTracker task_tracker; | 325 TaskTracker task_tracker; |
| 296 | 326 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 331 EXPECT_NE(task_raw, sequence->PeekTask()); | 361 EXPECT_NE(task_raw, sequence->PeekTask()); |
| 332 sequence->PopTask(); | 362 sequence->PopTask(); |
| 333 EXPECT_EQ(task_raw, sequence->PeekTask()); | 363 EXPECT_EQ(task_raw, sequence->PeekTask()); |
| 334 sequence->PopTask(); | 364 sequence->PopTask(); |
| 335 EXPECT_EQ(nullptr, sequence->PeekTask()); | 365 EXPECT_EQ(nullptr, sequence->PeekTask()); |
| 336 } | 366 } |
| 337 | 367 |
| 338 } // namespace | 368 } // namespace |
| 339 } // namespace internal | 369 } // namespace internal |
| 340 } // namespace base | 370 } // namespace base |
| OLD | NEW |