OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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_single_thread_task_runner_manager.h" | 5 #include "base/task_scheduler/scheduler_single_thread_task_runner_manager.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
9 #include "base/synchronization/atomic_flag.h" | 9 #include "base/synchronization/atomic_flag.h" |
10 #include "base/synchronization/lock.h" | 10 #include "base/synchronization/lock.h" |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 ADD_FAILURE() << "Ran a task that shouldn't run."; | 86 ADD_FAILURE() << "Ran a task that shouldn't run."; |
87 } | 87 } |
88 | 88 |
89 } // namespace | 89 } // namespace |
90 | 90 |
91 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, DifferentThreadsUsed) { | 91 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, DifferentThreadsUsed) { |
92 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = | 92 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = |
93 single_thread_task_runner_manager_ | 93 single_thread_task_runner_manager_ |
94 ->CreateSingleThreadTaskRunnerWithTraits( | 94 ->CreateSingleThreadTaskRunnerWithTraits( |
95 "A", ThreadPriority::NORMAL, | 95 "A", ThreadPriority::NORMAL, |
96 {TaskShutdownBehavior::BLOCK_SHUTDOWN}); | 96 {TaskShutdownBehavior::BLOCK_SHUTDOWN}, |
| 97 SingleThreadTaskRunnerThreadMode::DEDICATED); |
97 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = | 98 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = |
98 single_thread_task_runner_manager_ | 99 single_thread_task_runner_manager_ |
99 ->CreateSingleThreadTaskRunnerWithTraits( | 100 ->CreateSingleThreadTaskRunnerWithTraits( |
100 "B", ThreadPriority::NORMAL, | 101 "B", ThreadPriority::NORMAL, |
101 {TaskShutdownBehavior::BLOCK_SHUTDOWN}); | 102 {TaskShutdownBehavior::BLOCK_SHUTDOWN}, |
| 103 SingleThreadTaskRunnerThreadMode::DEDICATED); |
102 | 104 |
103 PlatformThreadRef thread_ref_1; | 105 PlatformThreadRef thread_ref_1; |
104 task_runner_1->PostTask(FROM_HERE, | 106 task_runner_1->PostTask(FROM_HERE, |
105 BindOnce(&CaptureThreadRef, &thread_ref_1)); | 107 BindOnce(&CaptureThreadRef, &thread_ref_1)); |
106 PlatformThreadRef thread_ref_2; | 108 PlatformThreadRef thread_ref_2; |
107 task_runner_2->PostTask(FROM_HERE, | 109 task_runner_2->PostTask(FROM_HERE, |
108 BindOnce(&CaptureThreadRef, &thread_ref_2)); | 110 BindOnce(&CaptureThreadRef, &thread_ref_2)); |
109 | 111 |
110 task_tracker_.Shutdown(); | 112 task_tracker_.Shutdown(); |
111 | 113 |
112 ASSERT_FALSE(thread_ref_1.is_null()); | 114 ASSERT_FALSE(thread_ref_1.is_null()); |
113 ASSERT_FALSE(thread_ref_2.is_null()); | 115 ASSERT_FALSE(thread_ref_2.is_null()); |
114 EXPECT_NE(thread_ref_1, thread_ref_2); | 116 EXPECT_NE(thread_ref_1, thread_ref_2); |
115 } | 117 } |
116 | 118 |
117 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PrioritySetCorrectly) { | 119 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, SameThreadUsed) { |
| 120 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = |
| 121 single_thread_task_runner_manager_ |
| 122 ->CreateSingleThreadTaskRunnerWithTraits( |
| 123 "A", ThreadPriority::NORMAL, |
| 124 {TaskShutdownBehavior::BLOCK_SHUTDOWN}, |
| 125 SingleThreadTaskRunnerThreadMode::SHARED); |
| 126 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = |
| 127 single_thread_task_runner_manager_ |
| 128 ->CreateSingleThreadTaskRunnerWithTraits( |
| 129 "B", ThreadPriority::NORMAL, |
| 130 {TaskShutdownBehavior::BLOCK_SHUTDOWN}, |
| 131 SingleThreadTaskRunnerThreadMode::SHARED); |
| 132 |
| 133 PlatformThreadRef thread_ref_1; |
| 134 task_runner_1->PostTask(FROM_HERE, |
| 135 BindOnce(&CaptureThreadRef, &thread_ref_1)); |
| 136 PlatformThreadRef thread_ref_2; |
| 137 task_runner_2->PostTask(FROM_HERE, |
| 138 BindOnce(&CaptureThreadRef, &thread_ref_2)); |
| 139 |
| 140 task_tracker_.Shutdown(); |
| 141 |
| 142 ASSERT_FALSE(thread_ref_1.is_null()); |
| 143 ASSERT_FALSE(thread_ref_2.is_null()); |
| 144 EXPECT_EQ(thread_ref_1, thread_ref_2); |
| 145 } |
| 146 |
| 147 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, |
| 148 RunsTasksOnCurrentThread) { |
| 149 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = |
| 150 single_thread_task_runner_manager_ |
| 151 ->CreateSingleThreadTaskRunnerWithTraits( |
| 152 "A", ThreadPriority::NORMAL, |
| 153 {TaskShutdownBehavior::BLOCK_SHUTDOWN}, |
| 154 SingleThreadTaskRunnerThreadMode::DEDICATED); |
| 155 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = |
| 156 single_thread_task_runner_manager_ |
| 157 ->CreateSingleThreadTaskRunnerWithTraits( |
| 158 "B", ThreadPriority::NORMAL, |
| 159 {TaskShutdownBehavior::BLOCK_SHUTDOWN}, |
| 160 SingleThreadTaskRunnerThreadMode::DEDICATED); |
| 161 |
| 162 EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread()); |
| 163 EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread()); |
| 164 |
| 165 task_runner_1->PostTask( |
| 166 FROM_HERE, BindOnce( |
| 167 [](scoped_refptr<SingleThreadTaskRunner> task_runner_1, |
| 168 scoped_refptr<SingleThreadTaskRunner> task_runner_2) { |
| 169 EXPECT_TRUE(task_runner_1->RunsTasksOnCurrentThread()); |
| 170 EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread()); |
| 171 }, |
| 172 task_runner_1, task_runner_2)); |
| 173 |
| 174 task_runner_2->PostTask( |
| 175 FROM_HERE, BindOnce( |
| 176 [](scoped_refptr<SingleThreadTaskRunner> task_runner_1, |
| 177 scoped_refptr<SingleThreadTaskRunner> task_runner_2) { |
| 178 EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread()); |
| 179 EXPECT_TRUE(task_runner_2->RunsTasksOnCurrentThread()); |
| 180 }, |
| 181 task_runner_1, task_runner_2)); |
| 182 |
| 183 task_tracker_.Shutdown(); |
| 184 } |
| 185 |
| 186 namespace { |
| 187 |
| 188 class TaskSchedulerSingleThreadTaskRunnerManagerCommonTest |
| 189 : public TaskSchedulerSingleThreadTaskRunnerManagerTest, |
| 190 public ::testing::WithParamInterface<SingleThreadTaskRunnerThreadMode> { |
| 191 public: |
| 192 TaskSchedulerSingleThreadTaskRunnerManagerCommonTest() = default; |
| 193 |
| 194 private: |
| 195 DISALLOW_COPY_AND_ASSIGN( |
| 196 TaskSchedulerSingleThreadTaskRunnerManagerCommonTest); |
| 197 }; |
| 198 |
| 199 } // namespace |
| 200 |
| 201 TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, |
| 202 PrioritySetCorrectly) { |
118 // Why are events used here instead of the task tracker? | 203 // Why are events used here instead of the task tracker? |
119 // Shutting down can cause priorities to get raised. This means we have to use | 204 // Shutting down can cause priorities to get raised. This means we have to use |
120 // events to determine when a task is run. | 205 // events to determine when a task is run. |
121 scoped_refptr<SingleThreadTaskRunner> task_runner_background = | 206 scoped_refptr<SingleThreadTaskRunner> task_runner_background = |
122 single_thread_task_runner_manager_ | 207 single_thread_task_runner_manager_ |
123 ->CreateSingleThreadTaskRunnerWithTraits("Background", | 208 ->CreateSingleThreadTaskRunnerWithTraits( |
124 ThreadPriority::BACKGROUND, | 209 "Background", ThreadPriority::BACKGROUND, |
125 {TaskPriority::BACKGROUND}); | 210 {TaskPriority::BACKGROUND}, GetParam()); |
126 scoped_refptr<SingleThreadTaskRunner> task_runner_normal = | 211 scoped_refptr<SingleThreadTaskRunner> task_runner_normal = |
127 single_thread_task_runner_manager_ | 212 single_thread_task_runner_manager_ |
128 ->CreateSingleThreadTaskRunnerWithTraits( | 213 ->CreateSingleThreadTaskRunnerWithTraits( |
129 "Normal", ThreadPriority::NORMAL, {TaskPriority::USER_VISIBLE}); | 214 "Normal", ThreadPriority::NORMAL, {TaskPriority::USER_VISIBLE}, |
| 215 GetParam()); |
130 | 216 |
131 ThreadPriority thread_priority_background; | 217 ThreadPriority thread_priority_background; |
132 task_runner_background->PostTask( | 218 task_runner_background->PostTask( |
133 FROM_HERE, BindOnce(&CaptureThreadPriority, &thread_priority_background)); | 219 FROM_HERE, BindOnce(&CaptureThreadPriority, &thread_priority_background)); |
134 WaitableEvent waitable_event_background( | 220 WaitableEvent waitable_event_background( |
135 WaitableEvent::ResetPolicy::MANUAL, | 221 WaitableEvent::ResetPolicy::MANUAL, |
136 WaitableEvent::InitialState::NOT_SIGNALED); | 222 WaitableEvent::InitialState::NOT_SIGNALED); |
137 task_runner_background->PostTask( | 223 task_runner_background->PostTask( |
138 FROM_HERE, | 224 FROM_HERE, |
139 BindOnce(&WaitableEvent::Signal, Unretained(&waitable_event_background))); | 225 BindOnce(&WaitableEvent::Signal, Unretained(&waitable_event_background))); |
(...skipping 11 matching lines...) Expand all Loading... |
151 waitable_event_background.Wait(); | 237 waitable_event_background.Wait(); |
152 waitable_event_normal.Wait(); | 238 waitable_event_normal.Wait(); |
153 | 239 |
154 if (Lock::HandlesMultipleThreadPriorities()) | 240 if (Lock::HandlesMultipleThreadPriorities()) |
155 EXPECT_EQ(ThreadPriority::BACKGROUND, thread_priority_background); | 241 EXPECT_EQ(ThreadPriority::BACKGROUND, thread_priority_background); |
156 else | 242 else |
157 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_background); | 243 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_background); |
158 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_normal); | 244 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_normal); |
159 } | 245 } |
160 | 246 |
161 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PostTaskAfterShutdown) { | 247 TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, |
162 auto task_runner = single_thread_task_runner_manager_ | 248 PostTaskAfterShutdown) { |
163 ->CreateSingleThreadTaskRunnerWithTraits( | 249 auto task_runner = |
164 "A", ThreadPriority::NORMAL, TaskTraits()); | 250 single_thread_task_runner_manager_ |
| 251 ->CreateSingleThreadTaskRunnerWithTraits("A", ThreadPriority::NORMAL, |
| 252 TaskTraits(), GetParam()); |
165 task_tracker_.Shutdown(); | 253 task_tracker_.Shutdown(); |
166 EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun))); | 254 EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun))); |
167 } | 255 } |
168 | 256 |
169 // Verify that a Task runs shortly after its delay expires. | 257 // Verify that a Task runs shortly after its delay expires. |
170 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PostDelayedTask) { | 258 TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, PostDelayedTask) { |
171 TimeTicks start_time = TimeTicks::Now(); | 259 TimeTicks start_time = TimeTicks::Now(); |
172 | 260 |
173 // Post a task with a short delay. | 261 // Post a task with a short delay. |
174 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, | 262 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, |
175 WaitableEvent::InitialState::NOT_SIGNALED); | 263 WaitableEvent::InitialState::NOT_SIGNALED); |
176 auto task_runner = single_thread_task_runner_manager_ | 264 auto task_runner = |
177 ->CreateSingleThreadTaskRunnerWithTraits( | 265 single_thread_task_runner_manager_ |
178 "A", ThreadPriority::NORMAL, TaskTraits()); | 266 ->CreateSingleThreadTaskRunnerWithTraits("A", ThreadPriority::NORMAL, |
| 267 TaskTraits(), GetParam()); |
179 EXPECT_TRUE(task_runner->PostDelayedTask( | 268 EXPECT_TRUE(task_runner->PostDelayedTask( |
180 FROM_HERE, BindOnce(&WaitableEvent::Signal, Unretained(&task_ran)), | 269 FROM_HERE, BindOnce(&WaitableEvent::Signal, Unretained(&task_ran)), |
181 TestTimeouts::tiny_timeout())); | 270 TestTimeouts::tiny_timeout())); |
182 | 271 |
183 // Wait until the task runs. | 272 // Wait until the task runs. |
184 task_ran.Wait(); | 273 task_ran.Wait(); |
185 | 274 |
186 // Expect the task to run after its delay expires, but not more than 250 ms | 275 // Expect the task to run after its delay expires, but not more than 250 ms |
187 // after that. | 276 // after that. |
188 const TimeDelta actual_delay = TimeTicks::Now() - start_time; | 277 const TimeDelta actual_delay = TimeTicks::Now() - start_time; |
189 EXPECT_GE(actual_delay, TestTimeouts::tiny_timeout()); | 278 EXPECT_GE(actual_delay, TestTimeouts::tiny_timeout()); |
190 EXPECT_LT(actual_delay, | 279 EXPECT_LT(actual_delay, |
191 TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout()); | 280 TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout()); |
192 } | 281 } |
193 | 282 |
194 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, | 283 INSTANTIATE_TEST_CASE_P( |
195 RunsTasksOnCurrentThread) { | 284 AllModes, |
196 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = | 285 TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, |
197 single_thread_task_runner_manager_ | 286 ::testing::Values(SingleThreadTaskRunnerThreadMode::SHARED, |
198 ->CreateSingleThreadTaskRunnerWithTraits( | 287 SingleThreadTaskRunnerThreadMode::DEDICATED)); |
199 "A", ThreadPriority::NORMAL, | |
200 {TaskShutdownBehavior::BLOCK_SHUTDOWN}); | |
201 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = | |
202 single_thread_task_runner_manager_ | |
203 ->CreateSingleThreadTaskRunnerWithTraits( | |
204 "B", ThreadPriority::NORMAL, | |
205 {TaskShutdownBehavior::BLOCK_SHUTDOWN}); | |
206 | |
207 EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread()); | |
208 EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread()); | |
209 | |
210 task_runner_1->PostTask( | |
211 FROM_HERE, BindOnce( | |
212 [](scoped_refptr<SingleThreadTaskRunner> task_runner_1, | |
213 scoped_refptr<SingleThreadTaskRunner> task_runner_2) { | |
214 EXPECT_TRUE(task_runner_1->RunsTasksOnCurrentThread()); | |
215 EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread()); | |
216 }, | |
217 task_runner_1, task_runner_2)); | |
218 | |
219 task_runner_2->PostTask( | |
220 FROM_HERE, BindOnce( | |
221 [](scoped_refptr<SingleThreadTaskRunner> task_runner_1, | |
222 scoped_refptr<SingleThreadTaskRunner> task_runner_2) { | |
223 EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread()); | |
224 EXPECT_TRUE(task_runner_2->RunsTasksOnCurrentThread()); | |
225 }, | |
226 task_runner_1, task_runner_2)); | |
227 | |
228 task_tracker_.Shutdown(); | |
229 } | |
230 | 288 |
231 namespace { | 289 namespace { |
232 | 290 |
233 class CallJoinFromDifferentThread : public SimpleThread { | 291 class CallJoinFromDifferentThread : public SimpleThread { |
234 public: | 292 public: |
235 CallJoinFromDifferentThread( | 293 CallJoinFromDifferentThread( |
236 SchedulerSingleThreadTaskRunnerManager* manager_to_join) | 294 SchedulerSingleThreadTaskRunnerManager* manager_to_join) |
237 : SimpleThread("SchedulerSingleThreadTaskRunnerManagerJoinThread"), | 295 : SimpleThread("SchedulerSingleThreadTaskRunnerManagerJoinThread"), |
238 manager_to_join_(manager_to_join), | 296 manager_to_join_(manager_to_join), |
239 run_started_event_(WaitableEvent::ResetPolicy::MANUAL, | 297 run_started_event_(WaitableEvent::ResetPolicy::MANUAL, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 // because of a Join call. | 336 // because of a Join call. |
279 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, | 337 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, |
280 WaitableEvent::InitialState::NOT_SIGNALED); | 338 WaitableEvent::InitialState::NOT_SIGNALED); |
281 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, | 339 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, |
282 WaitableEvent::InitialState::NOT_SIGNALED); | 340 WaitableEvent::InitialState::NOT_SIGNALED); |
283 | 341 |
284 { | 342 { |
285 auto task_runner = | 343 auto task_runner = |
286 single_thread_task_runner_manager_ | 344 single_thread_task_runner_manager_ |
287 ->CreateSingleThreadTaskRunnerWithTraits( | 345 ->CreateSingleThreadTaskRunnerWithTraits( |
288 "A", ThreadPriority::NORMAL, {WithBaseSyncPrimitives()}); | 346 "A", ThreadPriority::NORMAL, {WithBaseSyncPrimitives()}, |
| 347 SingleThreadTaskRunnerThreadMode::DEDICATED); |
289 EXPECT_TRUE(task_runner->PostTask( | 348 EXPECT_TRUE(task_runner->PostTask( |
290 FROM_HERE, | 349 FROM_HERE, |
291 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); | 350 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); |
292 EXPECT_TRUE(task_runner->PostTask( | 351 EXPECT_TRUE(task_runner->PostTask( |
293 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); | 352 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); |
294 } | 353 } |
295 | 354 |
296 task_running.Wait(); | 355 task_running.Wait(); |
297 CallJoinFromDifferentThread join_from_different_thread( | 356 CallJoinFromDifferentThread join_from_different_thread( |
298 single_thread_task_runner_manager_.get()); | 357 single_thread_task_runner_manager_.get()); |
299 join_from_different_thread.Start(); | 358 join_from_different_thread.Start(); |
300 join_from_different_thread.WaitForRunToStart(); | 359 join_from_different_thread.WaitForRunToStart(); |
301 task_blocking.Signal(); | 360 task_blocking.Signal(); |
302 join_from_different_thread.Join(); | 361 join_from_different_thread.Join(); |
303 } | 362 } |
304 | 363 |
305 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, | 364 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, |
306 ConcurrentJoinExtraSkippedTask) { | 365 ConcurrentJoinExtraSkippedTask) { |
307 // Tests to make sure that tasks are properly cleaned up at Join, allowing | 366 // Tests to make sure that tasks are properly cleaned up at Join, allowing |
308 // SingleThreadTaskRunners to unregister themselves. | 367 // SingleThreadTaskRunners to unregister themselves. |
309 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, | 368 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, |
310 WaitableEvent::InitialState::NOT_SIGNALED); | 369 WaitableEvent::InitialState::NOT_SIGNALED); |
311 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, | 370 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, |
312 WaitableEvent::InitialState::NOT_SIGNALED); | 371 WaitableEvent::InitialState::NOT_SIGNALED); |
313 | 372 |
314 { | 373 { |
315 auto task_runner = | 374 auto task_runner = |
316 single_thread_task_runner_manager_ | 375 single_thread_task_runner_manager_ |
317 ->CreateSingleThreadTaskRunnerWithTraits( | 376 ->CreateSingleThreadTaskRunnerWithTraits( |
318 "A", ThreadPriority::NORMAL, {WithBaseSyncPrimitives()}); | 377 "A", ThreadPriority::NORMAL, {WithBaseSyncPrimitives()}, |
| 378 SingleThreadTaskRunnerThreadMode::DEDICATED); |
319 EXPECT_TRUE(task_runner->PostTask( | 379 EXPECT_TRUE(task_runner->PostTask( |
320 FROM_HERE, | 380 FROM_HERE, |
321 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); | 381 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); |
322 EXPECT_TRUE(task_runner->PostTask( | 382 EXPECT_TRUE(task_runner->PostTask( |
323 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); | 383 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); |
324 EXPECT_TRUE(task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing))); | 384 EXPECT_TRUE(task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing))); |
325 } | 385 } |
326 | 386 |
327 task_running.Wait(); | 387 task_running.Wait(); |
328 CallJoinFromDifferentThread join_from_different_thread( | 388 CallJoinFromDifferentThread join_from_different_thread( |
329 single_thread_task_runner_manager_.get()); | 389 single_thread_task_runner_manager_.get()); |
330 join_from_different_thread.Start(); | 390 join_from_different_thread.Start(); |
331 join_from_different_thread.WaitForRunToStart(); | 391 join_from_different_thread.WaitForRunToStart(); |
332 task_blocking.Signal(); | 392 task_blocking.Signal(); |
333 join_from_different_thread.Join(); | 393 join_from_different_thread.Join(); |
334 } | 394 } |
335 | 395 |
336 #if defined(OS_WIN) | 396 #if defined(OS_WIN) |
337 | 397 |
338 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, COMSTAInitialized) { | 398 TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, |
| 399 COMSTAInitialized) { |
339 scoped_refptr<SingleThreadTaskRunner> com_task_runner = | 400 scoped_refptr<SingleThreadTaskRunner> com_task_runner = |
340 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( | 401 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( |
341 "A", ThreadPriority::NORMAL, {TaskShutdownBehavior::BLOCK_SHUTDOWN}); | 402 "A", ThreadPriority::NORMAL, {TaskShutdownBehavior::BLOCK_SHUTDOWN}, |
| 403 GetParam()); |
342 | 404 |
343 com_task_runner->PostTask( | 405 com_task_runner->PostTask( |
344 FROM_HERE, BindOnce([]() { | 406 FROM_HERE, BindOnce([]() { |
345 HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); | 407 HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); |
346 if (SUCCEEDED(hr)) { | 408 if (SUCCEEDED(hr)) { |
347 ADD_FAILURE() << "COM STA was not initialized on this thread"; | 409 ADD_FAILURE() << "COM STA was not initialized on this thread"; |
348 CoUninitialize(); | 410 CoUninitialize(); |
349 } | 411 } |
350 })); | 412 })); |
351 | 413 |
352 task_tracker_.Shutdown(); | 414 task_tracker_.Shutdown(); |
353 } | 415 } |
354 | 416 |
| 417 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, COMSTASameThreadUsed) { |
| 418 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = |
| 419 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( |
| 420 "A", ThreadPriority::NORMAL, {TaskShutdownBehavior::BLOCK_SHUTDOWN}, |
| 421 SingleThreadTaskRunnerThreadMode::SHARED); |
| 422 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = |
| 423 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( |
| 424 "B", ThreadPriority::NORMAL, {TaskShutdownBehavior::BLOCK_SHUTDOWN}, |
| 425 SingleThreadTaskRunnerThreadMode::SHARED); |
| 426 |
| 427 PlatformThreadRef thread_ref_1; |
| 428 task_runner_1->PostTask(FROM_HERE, |
| 429 BindOnce(&CaptureThreadRef, &thread_ref_1)); |
| 430 PlatformThreadRef thread_ref_2; |
| 431 task_runner_2->PostTask(FROM_HERE, |
| 432 BindOnce(&CaptureThreadRef, &thread_ref_2)); |
| 433 |
| 434 task_tracker_.Shutdown(); |
| 435 |
| 436 ASSERT_FALSE(thread_ref_1.is_null()); |
| 437 ASSERT_FALSE(thread_ref_2.is_null()); |
| 438 EXPECT_EQ(thread_ref_1, thread_ref_2); |
| 439 } |
| 440 |
355 namespace { | 441 namespace { |
356 | 442 |
357 const wchar_t* const kTestWindowClassName = | 443 const wchar_t* const kTestWindowClassName = |
358 L"TaskSchedulerSingleThreadTaskRunnerManagerTestWinMessageWindow"; | 444 L"TaskSchedulerSingleThreadTaskRunnerManagerTestWinMessageWindow"; |
359 | 445 |
360 class TaskSchedulerSingleThreadTaskRunnerManagerTestWin | 446 class TaskSchedulerSingleThreadTaskRunnerManagerTestWin |
361 : public TaskSchedulerSingleThreadTaskRunnerManagerTest { | 447 : public TaskSchedulerSingleThreadTaskRunnerManagerTest { |
362 public: | 448 public: |
363 TaskSchedulerSingleThreadTaskRunnerManagerTestWin() = default; | 449 TaskSchedulerSingleThreadTaskRunnerManagerTestWin() = default; |
364 | 450 |
(...skipping 28 matching lines...) Expand all Loading... |
393 bool register_class_succeeded_ = false; | 479 bool register_class_succeeded_ = false; |
394 | 480 |
395 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTestWin); | 481 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTestWin); |
396 }; | 482 }; |
397 | 483 |
398 } // namespace | 484 } // namespace |
399 | 485 |
400 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTestWin, PumpsMessages) { | 486 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTestWin, PumpsMessages) { |
401 scoped_refptr<SingleThreadTaskRunner> com_task_runner = | 487 scoped_refptr<SingleThreadTaskRunner> com_task_runner = |
402 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( | 488 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( |
403 "A", ThreadPriority::NORMAL, {TaskShutdownBehavior::BLOCK_SHUTDOWN}); | 489 "A", ThreadPriority::NORMAL, {TaskShutdownBehavior::BLOCK_SHUTDOWN}, |
| 490 SingleThreadTaskRunnerThreadMode::DEDICATED); |
404 HWND hwnd = nullptr; | 491 HWND hwnd = nullptr; |
405 // HWNDs process messages on the thread that created them, so we have to | 492 // HWNDs process messages on the thread that created them, so we have to |
406 // create them within the context of the task runner to properly simulate a | 493 // create them within the context of the task runner to properly simulate a |
407 // COM callback. | 494 // COM callback. |
408 com_task_runner->PostTask( | 495 com_task_runner->PostTask( |
409 FROM_HERE, | 496 FROM_HERE, |
410 BindOnce( | 497 BindOnce( |
411 [](TaskSchedulerSingleThreadTaskRunnerManagerTestWin* test_harness, | 498 [](TaskSchedulerSingleThreadTaskRunnerManagerTestWin* test_harness, |
412 HWND* hwnd) { *hwnd = test_harness->CreateTestWindow(); }, | 499 HWND* hwnd) { *hwnd = test_harness->CreateTestWindow(); }, |
413 Unretained(this), &hwnd)); | 500 Unretained(this), &hwnd)); |
(...skipping 30 matching lines...) Expand all Loading... |
444 | 531 |
445 } // namespace | 532 } // namespace |
446 | 533 |
447 // Verify that a task posted before Start() doesn't run until Start() is called. | 534 // Verify that a task posted before Start() doesn't run until Start() is called. |
448 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerStartTest, | 535 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerStartTest, |
449 PostTaskBeforeStart) { | 536 PostTaskBeforeStart) { |
450 AtomicFlag manager_started; | 537 AtomicFlag manager_started; |
451 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, | 538 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, |
452 WaitableEvent::InitialState::NOT_SIGNALED); | 539 WaitableEvent::InitialState::NOT_SIGNALED); |
453 single_thread_task_runner_manager_ | 540 single_thread_task_runner_manager_ |
454 ->CreateSingleThreadTaskRunnerWithTraits("A", ThreadPriority::NORMAL, | 541 ->CreateSingleThreadTaskRunnerWithTraits( |
455 TaskTraits()) | 542 "A", ThreadPriority::NORMAL, TaskTraits(), |
| 543 SingleThreadTaskRunnerThreadMode::DEDICATED) |
456 ->PostTask( | 544 ->PostTask( |
457 FROM_HERE, | 545 FROM_HERE, |
458 BindOnce( | 546 BindOnce( |
459 [](WaitableEvent* task_running, AtomicFlag* manager_started) { | 547 [](WaitableEvent* task_running, AtomicFlag* manager_started) { |
460 task_running->Signal(); | 548 task_running->Signal(); |
461 | 549 |
462 // The task should not run before Start(). | 550 // The task should not run before Start(). |
463 EXPECT_TRUE(manager_started->IsSet()); | 551 EXPECT_TRUE(manager_started->IsSet()); |
464 }, | 552 }, |
465 Unretained(&task_running), Unretained(&manager_started))); | 553 Unretained(&task_running), Unretained(&manager_started))); |
466 | 554 |
467 // Wait a little bit to make sure that the task isn't scheduled before start. | 555 // Wait a little bit to make sure that the task isn't scheduled before start. |
468 // Note: This test won't catch a case where the task is scheduled between | 556 // Note: This test won't catch a case where the task is scheduled between |
469 // setting |manager_started| and calling Start(). However, we expect the test | 557 // setting |manager_started| and calling Start(). However, we expect the test |
470 // to be flaky if the tested code allows that to happen. | 558 // to be flaky if the tested code allows that to happen. |
471 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); | 559 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
472 manager_started.Set(); | 560 manager_started.Set(); |
473 single_thread_task_runner_manager_->Start(); | 561 single_thread_task_runner_manager_->Start(); |
474 | 562 |
475 // This should not hang if the task is scheduled after Start(). | 563 // This should not hang if the task is scheduled after Start(). |
476 task_running.Wait(); | 564 task_running.Wait(); |
477 } | 565 } |
478 | 566 |
479 } // namespace internal | 567 } // namespace internal |
480 } // namespace base | 568 } // namespace base |
OLD | NEW |