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