| 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 TaskTraits().WithShutdownBehavior( | 96 {TaskShutdownBehavior::BLOCK_SHUTDOWN}); |
| 97 TaskShutdownBehavior::BLOCK_SHUTDOWN)); | |
| 98 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = | 97 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = |
| 99 single_thread_task_runner_manager_ | 98 single_thread_task_runner_manager_ |
| 100 ->CreateSingleThreadTaskRunnerWithTraits( | 99 ->CreateSingleThreadTaskRunnerWithTraits( |
| 101 "B", ThreadPriority::NORMAL, | 100 "B", ThreadPriority::NORMAL, |
| 102 TaskTraits().WithShutdownBehavior( | 101 {TaskShutdownBehavior::BLOCK_SHUTDOWN}); |
| 103 TaskShutdownBehavior::BLOCK_SHUTDOWN)); | |
| 104 | 102 |
| 105 PlatformThreadRef thread_ref_1; | 103 PlatformThreadRef thread_ref_1; |
| 106 task_runner_1->PostTask(FROM_HERE, | 104 task_runner_1->PostTask(FROM_HERE, |
| 107 BindOnce(&CaptureThreadRef, &thread_ref_1)); | 105 BindOnce(&CaptureThreadRef, &thread_ref_1)); |
| 108 PlatformThreadRef thread_ref_2; | 106 PlatformThreadRef thread_ref_2; |
| 109 task_runner_2->PostTask(FROM_HERE, | 107 task_runner_2->PostTask(FROM_HERE, |
| 110 BindOnce(&CaptureThreadRef, &thread_ref_2)); | 108 BindOnce(&CaptureThreadRef, &thread_ref_2)); |
| 111 | 109 |
| 112 task_tracker_.Shutdown(); | 110 task_tracker_.Shutdown(); |
| 113 | 111 |
| 114 ASSERT_FALSE(thread_ref_1.is_null()); | 112 ASSERT_FALSE(thread_ref_1.is_null()); |
| 115 ASSERT_FALSE(thread_ref_2.is_null()); | 113 ASSERT_FALSE(thread_ref_2.is_null()); |
| 116 EXPECT_NE(thread_ref_1, thread_ref_2); | 114 EXPECT_NE(thread_ref_1, thread_ref_2); |
| 117 } | 115 } |
| 118 | 116 |
| 119 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PrioritySetCorrectly) { | 117 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PrioritySetCorrectly) { |
| 120 // Why are events used here instead of the task tracker? | 118 // Why are events used here instead of the task tracker? |
| 121 // Shutting down can cause priorities to get raised. This means we have to use | 119 // Shutting down can cause priorities to get raised. This means we have to use |
| 122 // events to determine when a task is run. | 120 // events to determine when a task is run. |
| 123 scoped_refptr<SingleThreadTaskRunner> task_runner_background = | 121 scoped_refptr<SingleThreadTaskRunner> task_runner_background = |
| 124 single_thread_task_runner_manager_ | 122 single_thread_task_runner_manager_ |
| 125 ->CreateSingleThreadTaskRunnerWithTraits( | 123 ->CreateSingleThreadTaskRunnerWithTraits("Background", |
| 126 "Background", ThreadPriority::BACKGROUND, | 124 ThreadPriority::BACKGROUND, |
| 127 TaskTraits().WithPriority(TaskPriority::BACKGROUND)); | 125 {TaskPriority::BACKGROUND}); |
| 128 scoped_refptr<SingleThreadTaskRunner> task_runner_normal = | 126 scoped_refptr<SingleThreadTaskRunner> task_runner_normal = |
| 129 single_thread_task_runner_manager_ | 127 single_thread_task_runner_manager_ |
| 130 ->CreateSingleThreadTaskRunnerWithTraits( | 128 ->CreateSingleThreadTaskRunnerWithTraits( |
| 131 "Normal", ThreadPriority::NORMAL, | 129 "Normal", ThreadPriority::NORMAL, {TaskPriority::USER_VISIBLE}); |
| 132 TaskTraits().WithPriority(TaskPriority::USER_VISIBLE)); | |
| 133 | 130 |
| 134 ThreadPriority thread_priority_background; | 131 ThreadPriority thread_priority_background; |
| 135 task_runner_background->PostTask( | 132 task_runner_background->PostTask( |
| 136 FROM_HERE, BindOnce(&CaptureThreadPriority, &thread_priority_background)); | 133 FROM_HERE, BindOnce(&CaptureThreadPriority, &thread_priority_background)); |
| 137 WaitableEvent waitable_event_background( | 134 WaitableEvent waitable_event_background( |
| 138 WaitableEvent::ResetPolicy::MANUAL, | 135 WaitableEvent::ResetPolicy::MANUAL, |
| 139 WaitableEvent::InitialState::NOT_SIGNALED); | 136 WaitableEvent::InitialState::NOT_SIGNALED); |
| 140 task_runner_background->PostTask( | 137 task_runner_background->PostTask( |
| 141 FROM_HERE, | 138 FROM_HERE, |
| 142 BindOnce(&WaitableEvent::Signal, Unretained(&waitable_event_background))); | 139 BindOnce(&WaitableEvent::Signal, Unretained(&waitable_event_background))); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 EXPECT_LT(actual_delay, | 190 EXPECT_LT(actual_delay, |
| 194 TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout()); | 191 TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout()); |
| 195 } | 192 } |
| 196 | 193 |
| 197 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, | 194 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, |
| 198 RunsTasksOnCurrentThread) { | 195 RunsTasksOnCurrentThread) { |
| 199 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = | 196 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = |
| 200 single_thread_task_runner_manager_ | 197 single_thread_task_runner_manager_ |
| 201 ->CreateSingleThreadTaskRunnerWithTraits( | 198 ->CreateSingleThreadTaskRunnerWithTraits( |
| 202 "A", ThreadPriority::NORMAL, | 199 "A", ThreadPriority::NORMAL, |
| 203 TaskTraits().WithShutdownBehavior( | 200 {TaskShutdownBehavior::BLOCK_SHUTDOWN}); |
| 204 TaskShutdownBehavior::BLOCK_SHUTDOWN)); | |
| 205 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = | 201 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = |
| 206 single_thread_task_runner_manager_ | 202 single_thread_task_runner_manager_ |
| 207 ->CreateSingleThreadTaskRunnerWithTraits( | 203 ->CreateSingleThreadTaskRunnerWithTraits( |
| 208 "B", ThreadPriority::NORMAL, | 204 "B", ThreadPriority::NORMAL, |
| 209 TaskTraits().WithShutdownBehavior( | 205 {TaskShutdownBehavior::BLOCK_SHUTDOWN}); |
| 210 TaskShutdownBehavior::BLOCK_SHUTDOWN)); | |
| 211 | 206 |
| 212 EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread()); | 207 EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread()); |
| 213 EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread()); | 208 EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread()); |
| 214 | 209 |
| 215 task_runner_1->PostTask( | 210 task_runner_1->PostTask( |
| 216 FROM_HERE, BindOnce( | 211 FROM_HERE, BindOnce( |
| 217 [](scoped_refptr<SingleThreadTaskRunner> task_runner_1, | 212 [](scoped_refptr<SingleThreadTaskRunner> task_runner_1, |
| 218 scoped_refptr<SingleThreadTaskRunner> task_runner_2) { | 213 scoped_refptr<SingleThreadTaskRunner> task_runner_2) { |
| 219 EXPECT_TRUE(task_runner_1->RunsTasksOnCurrentThread()); | 214 EXPECT_TRUE(task_runner_1->RunsTasksOnCurrentThread()); |
| 220 EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread()); | 215 EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread()); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 | 275 |
| 281 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, ConcurrentJoin) { | 276 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, ConcurrentJoin) { |
| 282 // Exercises the codepath where the workers are unavailable for unregistration | 277 // Exercises the codepath where the workers are unavailable for unregistration |
| 283 // because of a Join call. | 278 // because of a Join call. |
| 284 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, | 279 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, |
| 285 WaitableEvent::InitialState::NOT_SIGNALED); | 280 WaitableEvent::InitialState::NOT_SIGNALED); |
| 286 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, | 281 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, |
| 287 WaitableEvent::InitialState::NOT_SIGNALED); | 282 WaitableEvent::InitialState::NOT_SIGNALED); |
| 288 | 283 |
| 289 { | 284 { |
| 290 auto task_runner = single_thread_task_runner_manager_ | 285 auto task_runner = |
| 291 ->CreateSingleThreadTaskRunnerWithTraits( | 286 single_thread_task_runner_manager_ |
| 292 "A", ThreadPriority::NORMAL, | 287 ->CreateSingleThreadTaskRunnerWithTraits( |
| 293 TaskTraits().WithBaseSyncPrimitives()); | 288 "A", ThreadPriority::NORMAL, {WithBaseSyncPrimitives()}); |
| 294 EXPECT_TRUE(task_runner->PostTask( | 289 EXPECT_TRUE(task_runner->PostTask( |
| 295 FROM_HERE, | 290 FROM_HERE, |
| 296 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); | 291 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); |
| 297 EXPECT_TRUE(task_runner->PostTask( | 292 EXPECT_TRUE(task_runner->PostTask( |
| 298 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); | 293 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); |
| 299 } | 294 } |
| 300 | 295 |
| 301 task_running.Wait(); | 296 task_running.Wait(); |
| 302 CallJoinFromDifferentThread join_from_different_thread( | 297 CallJoinFromDifferentThread join_from_different_thread( |
| 303 single_thread_task_runner_manager_.get()); | 298 single_thread_task_runner_manager_.get()); |
| 304 join_from_different_thread.Start(); | 299 join_from_different_thread.Start(); |
| 305 join_from_different_thread.WaitForRunToStart(); | 300 join_from_different_thread.WaitForRunToStart(); |
| 306 task_blocking.Signal(); | 301 task_blocking.Signal(); |
| 307 join_from_different_thread.Join(); | 302 join_from_different_thread.Join(); |
| 308 } | 303 } |
| 309 | 304 |
| 310 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, | 305 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, |
| 311 ConcurrentJoinExtraSkippedTask) { | 306 ConcurrentJoinExtraSkippedTask) { |
| 312 // Tests to make sure that tasks are properly cleaned up at Join, allowing | 307 // Tests to make sure that tasks are properly cleaned up at Join, allowing |
| 313 // SingleThreadTaskRunners to unregister themselves. | 308 // SingleThreadTaskRunners to unregister themselves. |
| 314 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, | 309 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, |
| 315 WaitableEvent::InitialState::NOT_SIGNALED); | 310 WaitableEvent::InitialState::NOT_SIGNALED); |
| 316 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, | 311 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, |
| 317 WaitableEvent::InitialState::NOT_SIGNALED); | 312 WaitableEvent::InitialState::NOT_SIGNALED); |
| 318 | 313 |
| 319 { | 314 { |
| 320 auto task_runner = single_thread_task_runner_manager_ | 315 auto task_runner = |
| 321 ->CreateSingleThreadTaskRunnerWithTraits( | 316 single_thread_task_runner_manager_ |
| 322 "A", ThreadPriority::NORMAL, | 317 ->CreateSingleThreadTaskRunnerWithTraits( |
| 323 TaskTraits().WithBaseSyncPrimitives()); | 318 "A", ThreadPriority::NORMAL, {WithBaseSyncPrimitives()}); |
| 324 EXPECT_TRUE(task_runner->PostTask( | 319 EXPECT_TRUE(task_runner->PostTask( |
| 325 FROM_HERE, | 320 FROM_HERE, |
| 326 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); | 321 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); |
| 327 EXPECT_TRUE(task_runner->PostTask( | 322 EXPECT_TRUE(task_runner->PostTask( |
| 328 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); | 323 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); |
| 329 EXPECT_TRUE(task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing))); | 324 EXPECT_TRUE(task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing))); |
| 330 } | 325 } |
| 331 | 326 |
| 332 task_running.Wait(); | 327 task_running.Wait(); |
| 333 CallJoinFromDifferentThread join_from_different_thread( | 328 CallJoinFromDifferentThread join_from_different_thread( |
| 334 single_thread_task_runner_manager_.get()); | 329 single_thread_task_runner_manager_.get()); |
| 335 join_from_different_thread.Start(); | 330 join_from_different_thread.Start(); |
| 336 join_from_different_thread.WaitForRunToStart(); | 331 join_from_different_thread.WaitForRunToStart(); |
| 337 task_blocking.Signal(); | 332 task_blocking.Signal(); |
| 338 join_from_different_thread.Join(); | 333 join_from_different_thread.Join(); |
| 339 } | 334 } |
| 340 | 335 |
| 341 #if defined(OS_WIN) | 336 #if defined(OS_WIN) |
| 342 | 337 |
| 343 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, COMSTAInitialized) { | 338 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, COMSTAInitialized) { |
| 344 scoped_refptr<SingleThreadTaskRunner> com_task_runner = | 339 scoped_refptr<SingleThreadTaskRunner> com_task_runner = |
| 345 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( | 340 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( |
| 346 "A", ThreadPriority::NORMAL, | 341 "A", ThreadPriority::NORMAL, {TaskShutdownBehavior::BLOCK_SHUTDOWN}); |
| 347 TaskTraits().WithShutdownBehavior( | |
| 348 TaskShutdownBehavior::BLOCK_SHUTDOWN)); | |
| 349 | 342 |
| 350 com_task_runner->PostTask( | 343 com_task_runner->PostTask( |
| 351 FROM_HERE, BindOnce([]() { | 344 FROM_HERE, BindOnce([]() { |
| 352 HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); | 345 HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); |
| 353 if (SUCCEEDED(hr)) { | 346 if (SUCCEEDED(hr)) { |
| 354 ADD_FAILURE() << "COM STA was not initialized on this thread"; | 347 ADD_FAILURE() << "COM STA was not initialized on this thread"; |
| 355 CoUninitialize(); | 348 CoUninitialize(); |
| 356 } | 349 } |
| 357 })); | 350 })); |
| 358 | 351 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 bool register_class_succeeded_ = false; | 393 bool register_class_succeeded_ = false; |
| 401 | 394 |
| 402 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTestWin); | 395 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTestWin); |
| 403 }; | 396 }; |
| 404 | 397 |
| 405 } // namespace | 398 } // namespace |
| 406 | 399 |
| 407 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTestWin, PumpsMessages) { | 400 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTestWin, PumpsMessages) { |
| 408 scoped_refptr<SingleThreadTaskRunner> com_task_runner = | 401 scoped_refptr<SingleThreadTaskRunner> com_task_runner = |
| 409 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( | 402 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( |
| 410 "A", ThreadPriority::NORMAL, | 403 "A", ThreadPriority::NORMAL, {TaskShutdownBehavior::BLOCK_SHUTDOWN}); |
| 411 TaskTraits().WithShutdownBehavior( | |
| 412 TaskShutdownBehavior::BLOCK_SHUTDOWN)); | |
| 413 HWND hwnd = nullptr; | 404 HWND hwnd = nullptr; |
| 414 // HWNDs process messages on the thread that created them, so we have to | 405 // HWNDs process messages on the thread that created them, so we have to |
| 415 // create them within the context of the task runner to properly simulate a | 406 // create them within the context of the task runner to properly simulate a |
| 416 // COM callback. | 407 // COM callback. |
| 417 com_task_runner->PostTask( | 408 com_task_runner->PostTask( |
| 418 FROM_HERE, | 409 FROM_HERE, |
| 419 BindOnce( | 410 BindOnce( |
| 420 [](TaskSchedulerSingleThreadTaskRunnerManagerTestWin* test_harness, | 411 [](TaskSchedulerSingleThreadTaskRunnerManagerTestWin* test_harness, |
| 421 HWND* hwnd) { *hwnd = test_harness->CreateTestWindow(); }, | 412 HWND* hwnd) { *hwnd = test_harness->CreateTestWindow(); }, |
| 422 Unretained(this), &hwnd)); | 413 Unretained(this), &hwnd)); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); | 471 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 481 manager_started.Set(); | 472 manager_started.Set(); |
| 482 single_thread_task_runner_manager_->Start(); | 473 single_thread_task_runner_manager_->Start(); |
| 483 | 474 |
| 484 // This should not hang if the task is scheduled after Start(). | 475 // This should not hang if the task is scheduled after Start(). |
| 485 task_running.Wait(); | 476 task_running.Wait(); |
| 486 } | 477 } |
| 487 | 478 |
| 488 } // namespace internal | 479 } // namespace internal |
| 489 } // namespace base | 480 } // namespace base |
| OLD | NEW |