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