| 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 14 matching lines...) Expand all Loading... |
| 25 #include <objbase.h> | 25 #include <objbase.h> |
| 26 | 26 |
| 27 #include "base/win/current_module.h" | 27 #include "base/win/current_module.h" |
| 28 #endif // defined(OS_WIN) | 28 #endif // defined(OS_WIN) |
| 29 | 29 |
| 30 namespace base { | 30 namespace base { |
| 31 namespace internal { | 31 namespace internal { |
| 32 | 32 |
| 33 namespace { | 33 namespace { |
| 34 | 34 |
| 35 enum WorkerPoolType : size_t { | |
| 36 BACKGROUND_WORKER_POOL = 0, | |
| 37 FOREGROUND_WORKER_POOL, | |
| 38 }; | |
| 39 | |
| 40 static size_t GetThreadPoolIndexForTraits(const TaskTraits& traits) { | |
| 41 return traits.priority() == TaskPriority::BACKGROUND ? BACKGROUND_WORKER_POOL | |
| 42 : FOREGROUND_WORKER_POOL; | |
| 43 } | |
| 44 | |
| 45 std::vector<SchedulerWorkerPoolParams> GetParamsVector() { | |
| 46 using StandbyThreadPolicy = SchedulerWorkerPoolParams::StandbyThreadPolicy; | |
| 47 | |
| 48 std::vector<SchedulerWorkerPoolParams> params_vector; | |
| 49 | |
| 50 DCHECK_EQ(BACKGROUND_WORKER_POOL, params_vector.size()); | |
| 51 params_vector.emplace_back("Background", ThreadPriority::BACKGROUND, | |
| 52 StandbyThreadPolicy::LAZY, 1U, TimeDelta::Max()); | |
| 53 | |
| 54 DCHECK_EQ(FOREGROUND_WORKER_POOL, params_vector.size()); | |
| 55 params_vector.emplace_back("Foreground", ThreadPriority::NORMAL, | |
| 56 StandbyThreadPolicy::LAZY, 1U, TimeDelta::Max()); | |
| 57 | |
| 58 return params_vector; | |
| 59 } | |
| 60 | |
| 61 class TaskSchedulerSingleThreadTaskRunnerManagerTest : public testing::Test { | 35 class TaskSchedulerSingleThreadTaskRunnerManagerTest : public testing::Test { |
| 62 public: | 36 public: |
| 63 TaskSchedulerSingleThreadTaskRunnerManagerTest() | 37 TaskSchedulerSingleThreadTaskRunnerManagerTest() |
| 64 : service_thread_("TaskSchedulerServiceThread") {} | 38 : service_thread_("TaskSchedulerServiceThread") {} |
| 65 | 39 |
| 66 void SetUp() override { | 40 void SetUp() override { |
| 67 service_thread_.Start(); | 41 service_thread_.Start(); |
| 68 | |
| 69 delayed_task_manager_ = | 42 delayed_task_manager_ = |
| 70 MakeUnique<DelayedTaskManager>(service_thread_.task_runner()); | 43 MakeUnique<DelayedTaskManager>(service_thread_.task_runner()); |
| 71 single_thread_task_runner_manager_ = | 44 single_thread_task_runner_manager_ = |
| 72 MakeUnique<SchedulerSingleThreadTaskRunnerManager>( | 45 MakeUnique<SchedulerSingleThreadTaskRunnerManager>( |
| 73 GetParamsVector(), Bind(&GetThreadPoolIndexForTraits), | |
| 74 &task_tracker_, delayed_task_manager_.get()); | 46 &task_tracker_, delayed_task_manager_.get()); |
| 75 StartSingleThreadTaskRunnerManagerFromSetUp(); | 47 StartSingleThreadTaskRunnerManagerFromSetUp(); |
| 76 } | 48 } |
| 77 | 49 |
| 78 void TearDown() override { | 50 void TearDown() override { |
| 79 TearDownSingleThreadTaskRunnerManager(); | 51 TearDownSingleThreadTaskRunnerManager(); |
| 80 delayed_task_manager_.reset(); | 52 delayed_task_manager_.reset(); |
| 81 service_thread_.Stop(); | 53 service_thread_.Stop(); |
| 82 } | 54 } |
| 83 | 55 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 void ShouldNotRun() { | 87 void ShouldNotRun() { |
| 116 ADD_FAILURE() << "Ran a task that shouldn't run."; | 88 ADD_FAILURE() << "Ran a task that shouldn't run."; |
| 117 } | 89 } |
| 118 | 90 |
| 119 } // namespace | 91 } // namespace |
| 120 | 92 |
| 121 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, DifferentThreadsUsed) { | 93 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, DifferentThreadsUsed) { |
| 122 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = | 94 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = |
| 123 single_thread_task_runner_manager_ | 95 single_thread_task_runner_manager_ |
| 124 ->CreateSingleThreadTaskRunnerWithTraits( | 96 ->CreateSingleThreadTaskRunnerWithTraits( |
| 97 "A", ThreadPriority::NORMAL, |
| 125 TaskTraits().WithShutdownBehavior( | 98 TaskTraits().WithShutdownBehavior( |
| 126 TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 99 TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| 127 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = | 100 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = |
| 128 single_thread_task_runner_manager_ | 101 single_thread_task_runner_manager_ |
| 129 ->CreateSingleThreadTaskRunnerWithTraits( | 102 ->CreateSingleThreadTaskRunnerWithTraits( |
| 103 "B", ThreadPriority::NORMAL, |
| 130 TaskTraits().WithShutdownBehavior( | 104 TaskTraits().WithShutdownBehavior( |
| 131 TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 105 TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| 132 | 106 |
| 133 PlatformThreadRef thread_ref_1; | 107 PlatformThreadRef thread_ref_1; |
| 134 task_runner_1->PostTask(FROM_HERE, | 108 task_runner_1->PostTask(FROM_HERE, |
| 135 BindOnce(&CaptureThreadRef, &thread_ref_1)); | 109 BindOnce(&CaptureThreadRef, &thread_ref_1)); |
| 136 PlatformThreadRef thread_ref_2; | 110 PlatformThreadRef thread_ref_2; |
| 137 task_runner_2->PostTask(FROM_HERE, | 111 task_runner_2->PostTask(FROM_HERE, |
| 138 BindOnce(&CaptureThreadRef, &thread_ref_2)); | 112 BindOnce(&CaptureThreadRef, &thread_ref_2)); |
| 139 | 113 |
| 140 task_tracker_.Shutdown(); | 114 task_tracker_.Shutdown(); |
| 141 | 115 |
| 142 ASSERT_FALSE(thread_ref_1.is_null()); | 116 ASSERT_FALSE(thread_ref_1.is_null()); |
| 143 ASSERT_FALSE(thread_ref_2.is_null()); | 117 ASSERT_FALSE(thread_ref_2.is_null()); |
| 144 EXPECT_NE(thread_ref_1, thread_ref_2); | 118 EXPECT_NE(thread_ref_1, thread_ref_2); |
| 145 } | 119 } |
| 146 | 120 |
| 147 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PrioritySetCorrectly) { | 121 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PrioritySetCorrectly) { |
| 148 // Why are events used here instead of the task tracker? | 122 // Why are events used here instead of the task tracker? |
| 149 // Shutting down can cause priorities to get raised. This means we have to use | 123 // Shutting down can cause priorities to get raised. This means we have to use |
| 150 // events to determine when a task is run. | 124 // events to determine when a task is run. |
| 151 scoped_refptr<SingleThreadTaskRunner> task_runner_background = | 125 scoped_refptr<SingleThreadTaskRunner> task_runner_background = |
| 152 single_thread_task_runner_manager_ | 126 single_thread_task_runner_manager_ |
| 153 ->CreateSingleThreadTaskRunnerWithTraits( | 127 ->CreateSingleThreadTaskRunnerWithTraits( |
| 128 "Background", ThreadPriority::BACKGROUND, |
| 154 TaskTraits().WithPriority(TaskPriority::BACKGROUND)); | 129 TaskTraits().WithPriority(TaskPriority::BACKGROUND)); |
| 155 scoped_refptr<SingleThreadTaskRunner> task_runner_user_visible = | 130 scoped_refptr<SingleThreadTaskRunner> task_runner_normal = |
| 156 single_thread_task_runner_manager_ | 131 single_thread_task_runner_manager_ |
| 157 ->CreateSingleThreadTaskRunnerWithTraits( | 132 ->CreateSingleThreadTaskRunnerWithTraits( |
| 133 "Normal", ThreadPriority::NORMAL, |
| 158 TaskTraits().WithPriority(TaskPriority::USER_VISIBLE)); | 134 TaskTraits().WithPriority(TaskPriority::USER_VISIBLE)); |
| 159 scoped_refptr<SingleThreadTaskRunner> task_runner_user_blocking = | |
| 160 single_thread_task_runner_manager_ | |
| 161 ->CreateSingleThreadTaskRunnerWithTraits( | |
| 162 TaskTraits() | |
| 163 .WithPriority(TaskPriority::USER_BLOCKING) | |
| 164 .WithShutdownBehavior(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | |
| 165 | 135 |
| 166 ThreadPriority thread_priority_background; | 136 ThreadPriority thread_priority_background; |
| 167 task_runner_background->PostTask( | 137 task_runner_background->PostTask( |
| 168 FROM_HERE, BindOnce(&CaptureThreadPriority, &thread_priority_background)); | 138 FROM_HERE, BindOnce(&CaptureThreadPriority, &thread_priority_background)); |
| 169 WaitableEvent waitable_event_background( | 139 WaitableEvent waitable_event_background( |
| 170 WaitableEvent::ResetPolicy::MANUAL, | 140 WaitableEvent::ResetPolicy::MANUAL, |
| 171 WaitableEvent::InitialState::NOT_SIGNALED); | 141 WaitableEvent::InitialState::NOT_SIGNALED); |
| 172 task_runner_background->PostTask( | 142 task_runner_background->PostTask( |
| 173 FROM_HERE, | 143 FROM_HERE, |
| 174 BindOnce(&WaitableEvent::Signal, Unretained(&waitable_event_background))); | 144 BindOnce(&WaitableEvent::Signal, Unretained(&waitable_event_background))); |
| 175 | 145 |
| 176 ThreadPriority thread_priority_user_visible; | 146 ThreadPriority thread_priority_normal; |
| 177 task_runner_user_visible->PostTask( | 147 task_runner_normal->PostTask( |
| 178 FROM_HERE, | 148 FROM_HERE, BindOnce(&CaptureThreadPriority, &thread_priority_normal)); |
| 179 BindOnce(&CaptureThreadPriority, &thread_priority_user_visible)); | 149 WaitableEvent waitable_event_normal( |
| 180 WaitableEvent waitable_event_user_visible( | |
| 181 WaitableEvent::ResetPolicy::MANUAL, | 150 WaitableEvent::ResetPolicy::MANUAL, |
| 182 WaitableEvent::InitialState::NOT_SIGNALED); | 151 WaitableEvent::InitialState::NOT_SIGNALED); |
| 183 task_runner_user_visible->PostTask( | 152 task_runner_normal->PostTask( |
| 184 FROM_HERE, BindOnce(&WaitableEvent::Signal, | |
| 185 Unretained(&waitable_event_user_visible))); | |
| 186 | |
| 187 ThreadPriority thread_priority_user_blocking; | |
| 188 task_runner_user_blocking->PostTask( | |
| 189 FROM_HERE, | 153 FROM_HERE, |
| 190 BindOnce(&CaptureThreadPriority, &thread_priority_user_blocking)); | 154 BindOnce(&WaitableEvent::Signal, Unretained(&waitable_event_normal))); |
| 191 WaitableEvent waitable_event_user_blocking( | |
| 192 WaitableEvent::ResetPolicy::MANUAL, | |
| 193 WaitableEvent::InitialState::NOT_SIGNALED); | |
| 194 task_runner_user_blocking->PostTask( | |
| 195 FROM_HERE, BindOnce(&WaitableEvent::Signal, | |
| 196 Unretained(&waitable_event_user_blocking))); | |
| 197 | 155 |
| 198 waitable_event_background.Wait(); | 156 waitable_event_background.Wait(); |
| 199 waitable_event_user_visible.Wait(); | 157 waitable_event_normal.Wait(); |
| 200 waitable_event_user_blocking.Wait(); | |
| 201 | 158 |
| 202 if (Lock::HandlesMultipleThreadPriorities()) | 159 if (Lock::HandlesMultipleThreadPriorities()) |
| 203 EXPECT_EQ(ThreadPriority::BACKGROUND, thread_priority_background); | 160 EXPECT_EQ(ThreadPriority::BACKGROUND, thread_priority_background); |
| 204 else | 161 else |
| 205 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_background); | 162 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_background); |
| 206 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_user_visible); | 163 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_normal); |
| 207 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_user_blocking); | |
| 208 } | 164 } |
| 209 | 165 |
| 210 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PostTaskAfterShutdown) { | 166 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PostTaskAfterShutdown) { |
| 211 auto task_runner = single_thread_task_runner_manager_ | 167 auto task_runner = single_thread_task_runner_manager_ |
| 212 ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()); | 168 ->CreateSingleThreadTaskRunnerWithTraits( |
| 169 "A", ThreadPriority::NORMAL, TaskTraits()); |
| 213 task_tracker_.Shutdown(); | 170 task_tracker_.Shutdown(); |
| 214 EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun))); | 171 EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun))); |
| 215 } | 172 } |
| 216 | 173 |
| 217 // Verify that a Task runs shortly after its delay expires. | 174 // Verify that a Task runs shortly after its delay expires. |
| 218 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PostDelayedTask) { | 175 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PostDelayedTask) { |
| 219 TimeTicks start_time = TimeTicks::Now(); | 176 TimeTicks start_time = TimeTicks::Now(); |
| 220 | 177 |
| 221 // Post a task with a short delay. | 178 // Post a task with a short delay. |
| 222 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, | 179 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, |
| 223 WaitableEvent::InitialState::NOT_SIGNALED); | 180 WaitableEvent::InitialState::NOT_SIGNALED); |
| 224 auto task_runner = single_thread_task_runner_manager_ | 181 auto task_runner = single_thread_task_runner_manager_ |
| 225 ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()); | 182 ->CreateSingleThreadTaskRunnerWithTraits( |
| 183 "A", ThreadPriority::NORMAL, TaskTraits()); |
| 226 EXPECT_TRUE(task_runner->PostDelayedTask( | 184 EXPECT_TRUE(task_runner->PostDelayedTask( |
| 227 FROM_HERE, BindOnce(&WaitableEvent::Signal, Unretained(&task_ran)), | 185 FROM_HERE, BindOnce(&WaitableEvent::Signal, Unretained(&task_ran)), |
| 228 TestTimeouts::tiny_timeout())); | 186 TestTimeouts::tiny_timeout())); |
| 229 | 187 |
| 230 // Wait until the task runs. | 188 // Wait until the task runs. |
| 231 task_ran.Wait(); | 189 task_ran.Wait(); |
| 232 | 190 |
| 233 // Expect the task to run after its delay expires, but not more than 250 ms | 191 // Expect the task to run after its delay expires, but not more than 250 ms |
| 234 // after that. | 192 // after that. |
| 235 const TimeDelta actual_delay = TimeTicks::Now() - start_time; | 193 const TimeDelta actual_delay = TimeTicks::Now() - start_time; |
| 236 EXPECT_GE(actual_delay, TestTimeouts::tiny_timeout()); | 194 EXPECT_GE(actual_delay, TestTimeouts::tiny_timeout()); |
| 237 EXPECT_LT(actual_delay, | 195 EXPECT_LT(actual_delay, |
| 238 TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout()); | 196 TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout()); |
| 239 } | 197 } |
| 240 | 198 |
| 241 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, | 199 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, |
| 242 RunsTasksOnCurrentThread) { | 200 RunsTasksOnCurrentThread) { |
| 243 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = | 201 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = |
| 244 single_thread_task_runner_manager_ | 202 single_thread_task_runner_manager_ |
| 245 ->CreateSingleThreadTaskRunnerWithTraits( | 203 ->CreateSingleThreadTaskRunnerWithTraits( |
| 204 "A", ThreadPriority::NORMAL, |
| 246 TaskTraits().WithShutdownBehavior( | 205 TaskTraits().WithShutdownBehavior( |
| 247 TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 206 TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| 248 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = | 207 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = |
| 249 single_thread_task_runner_manager_ | 208 single_thread_task_runner_manager_ |
| 250 ->CreateSingleThreadTaskRunnerWithTraits( | 209 ->CreateSingleThreadTaskRunnerWithTraits( |
| 210 "B", ThreadPriority::NORMAL, |
| 251 TaskTraits().WithShutdownBehavior( | 211 TaskTraits().WithShutdownBehavior( |
| 252 TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 212 TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| 253 | 213 |
| 254 EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread()); | 214 EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread()); |
| 255 EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread()); | 215 EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread()); |
| 256 | 216 |
| 257 task_runner_1->PostTask( | 217 task_runner_1->PostTask( |
| 258 FROM_HERE, BindOnce( | 218 FROM_HERE, BindOnce( |
| 259 [](scoped_refptr<SingleThreadTaskRunner> task_runner_1, | 219 [](scoped_refptr<SingleThreadTaskRunner> task_runner_1, |
| 260 scoped_refptr<SingleThreadTaskRunner> task_runner_2) { | 220 scoped_refptr<SingleThreadTaskRunner> task_runner_2) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 // Exercises the codepath where the workers are unavailable for unregistration | 284 // Exercises the codepath where the workers are unavailable for unregistration |
| 325 // because of a Join call. | 285 // because of a Join call. |
| 326 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, | 286 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, |
| 327 WaitableEvent::InitialState::NOT_SIGNALED); | 287 WaitableEvent::InitialState::NOT_SIGNALED); |
| 328 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, | 288 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, |
| 329 WaitableEvent::InitialState::NOT_SIGNALED); | 289 WaitableEvent::InitialState::NOT_SIGNALED); |
| 330 | 290 |
| 331 { | 291 { |
| 332 auto task_runner = single_thread_task_runner_manager_ | 292 auto task_runner = single_thread_task_runner_manager_ |
| 333 ->CreateSingleThreadTaskRunnerWithTraits( | 293 ->CreateSingleThreadTaskRunnerWithTraits( |
| 294 "A", ThreadPriority::NORMAL, |
| 334 TaskTraits().WithBaseSyncPrimitives()); | 295 TaskTraits().WithBaseSyncPrimitives()); |
| 335 EXPECT_TRUE(task_runner->PostTask( | 296 EXPECT_TRUE(task_runner->PostTask( |
| 336 FROM_HERE, | 297 FROM_HERE, |
| 337 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); | 298 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); |
| 338 EXPECT_TRUE(task_runner->PostTask( | 299 EXPECT_TRUE(task_runner->PostTask( |
| 339 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); | 300 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); |
| 340 } | 301 } |
| 341 | 302 |
| 342 task_running.Wait(); | 303 task_running.Wait(); |
| 343 CallJoinFromDifferentThread join_from_different_thread( | 304 CallJoinFromDifferentThread join_from_different_thread( |
| 344 single_thread_task_runner_manager_.get()); | 305 single_thread_task_runner_manager_.get()); |
| 345 join_from_different_thread.Start(); | 306 join_from_different_thread.Start(); |
| 346 join_from_different_thread.WaitForRunToStart(); | 307 join_from_different_thread.WaitForRunToStart(); |
| 347 task_blocking.Signal(); | 308 task_blocking.Signal(); |
| 348 join_from_different_thread.Join(); | 309 join_from_different_thread.Join(); |
| 349 } | 310 } |
| 350 | 311 |
| 351 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, | 312 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, |
| 352 ConcurrentJoinExtraSkippedTask) { | 313 ConcurrentJoinExtraSkippedTask) { |
| 353 // Tests to make sure that tasks are properly cleaned up at Join, allowing | 314 // Tests to make sure that tasks are properly cleaned up at Join, allowing |
| 354 // SingleThreadTaskRunners to unregister themselves. | 315 // SingleThreadTaskRunners to unregister themselves. |
| 355 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, | 316 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, |
| 356 WaitableEvent::InitialState::NOT_SIGNALED); | 317 WaitableEvent::InitialState::NOT_SIGNALED); |
| 357 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, | 318 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, |
| 358 WaitableEvent::InitialState::NOT_SIGNALED); | 319 WaitableEvent::InitialState::NOT_SIGNALED); |
| 359 | 320 |
| 360 { | 321 { |
| 361 auto task_runner = single_thread_task_runner_manager_ | 322 auto task_runner = single_thread_task_runner_manager_ |
| 362 ->CreateSingleThreadTaskRunnerWithTraits( | 323 ->CreateSingleThreadTaskRunnerWithTraits( |
| 324 "A", ThreadPriority::NORMAL, |
| 363 TaskTraits().WithBaseSyncPrimitives()); | 325 TaskTraits().WithBaseSyncPrimitives()); |
| 364 EXPECT_TRUE(task_runner->PostTask( | 326 EXPECT_TRUE(task_runner->PostTask( |
| 365 FROM_HERE, | 327 FROM_HERE, |
| 366 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); | 328 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); |
| 367 EXPECT_TRUE(task_runner->PostTask( | 329 EXPECT_TRUE(task_runner->PostTask( |
| 368 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); | 330 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); |
| 369 EXPECT_TRUE(task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing))); | 331 EXPECT_TRUE(task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing))); |
| 370 } | 332 } |
| 371 | 333 |
| 372 task_running.Wait(); | 334 task_running.Wait(); |
| 373 CallJoinFromDifferentThread join_from_different_thread( | 335 CallJoinFromDifferentThread join_from_different_thread( |
| 374 single_thread_task_runner_manager_.get()); | 336 single_thread_task_runner_manager_.get()); |
| 375 join_from_different_thread.Start(); | 337 join_from_different_thread.Start(); |
| 376 join_from_different_thread.WaitForRunToStart(); | 338 join_from_different_thread.WaitForRunToStart(); |
| 377 task_blocking.Signal(); | 339 task_blocking.Signal(); |
| 378 join_from_different_thread.Join(); | 340 join_from_different_thread.Join(); |
| 379 } | 341 } |
| 380 | 342 |
| 381 #if defined(OS_WIN) | 343 #if defined(OS_WIN) |
| 382 | 344 |
| 383 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, COMSTAInitialized) { | 345 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, COMSTAInitialized) { |
| 384 scoped_refptr<SingleThreadTaskRunner> com_task_runner = | 346 scoped_refptr<SingleThreadTaskRunner> com_task_runner = |
| 385 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( | 347 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( |
| 348 "A", ThreadPriority::NORMAL, |
| 386 TaskTraits().WithShutdownBehavior( | 349 TaskTraits().WithShutdownBehavior( |
| 387 TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 350 TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| 388 | 351 |
| 389 com_task_runner->PostTask( | 352 com_task_runner->PostTask( |
| 390 FROM_HERE, Bind([]() { | 353 FROM_HERE, BindOnce([]() { |
| 391 HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); | 354 HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); |
| 392 if (SUCCEEDED(hr)) { | 355 if (SUCCEEDED(hr)) { |
| 393 ADD_FAILURE() << "COM STA was not initialized on this thread"; | 356 ADD_FAILURE() << "COM STA was not initialized on this thread"; |
| 394 CoUninitialize(); | 357 CoUninitialize(); |
| 395 } | 358 } |
| 396 })); | 359 })); |
| 397 | 360 |
| 398 task_tracker_.Shutdown(); | 361 task_tracker_.Shutdown(); |
| 399 } | 362 } |
| 400 | 363 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 bool register_class_succeeded_ = false; | 402 bool register_class_succeeded_ = false; |
| 440 | 403 |
| 441 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTestWin); | 404 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTestWin); |
| 442 }; | 405 }; |
| 443 | 406 |
| 444 } // namespace | 407 } // namespace |
| 445 | 408 |
| 446 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTestWin, PumpsMessages) { | 409 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTestWin, PumpsMessages) { |
| 447 scoped_refptr<SingleThreadTaskRunner> com_task_runner = | 410 scoped_refptr<SingleThreadTaskRunner> com_task_runner = |
| 448 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( | 411 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( |
| 412 "A", ThreadPriority::NORMAL, |
| 449 TaskTraits().WithShutdownBehavior( | 413 TaskTraits().WithShutdownBehavior( |
| 450 TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 414 TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| 451 HWND hwnd = nullptr; | 415 HWND hwnd = nullptr; |
| 452 // HWNDs process messages on the thread that created them, so we have to | 416 // HWNDs process messages on the thread that created them, so we have to |
| 453 // create them within the context of the task runner to properly simulate a | 417 // create them within the context of the task runner to properly simulate a |
| 454 // COM callback. | 418 // COM callback. |
| 455 com_task_runner->PostTask( | 419 com_task_runner->PostTask( |
| 456 FROM_HERE, | 420 FROM_HERE, |
| 457 Bind([](TaskSchedulerSingleThreadTaskRunnerManagerTestWin* test_harness, | 421 BindOnce( |
| 458 HWND* hwnd) { *hwnd = test_harness->CreateTestWindow(); }, | 422 [](TaskSchedulerSingleThreadTaskRunnerManagerTestWin* test_harness, |
| 459 Unretained(this), &hwnd)); | 423 HWND* hwnd) { *hwnd = test_harness->CreateTestWindow(); }, |
| 424 Unretained(this), &hwnd)); |
| 460 | 425 |
| 461 task_tracker_.Flush(); | 426 task_tracker_.Flush(); |
| 462 | 427 |
| 463 ASSERT_NE(hwnd, nullptr); | 428 ASSERT_NE(hwnd, nullptr); |
| 464 // If the message pump isn't running, we will hang here. This simulates how | 429 // If the message pump isn't running, we will hang here. This simulates how |
| 465 // COM would receive a callback with its own message HWND. | 430 // COM would receive a callback with its own message HWND. |
| 466 SendMessage(hwnd, WM_USER, 0, 0); | 431 SendMessage(hwnd, WM_USER, 0, 0); |
| 467 | 432 |
| 468 com_task_runner->PostTask( | 433 com_task_runner->PostTask( |
| 469 FROM_HERE, Bind([](HWND hwnd) { ::DestroyWindow(hwnd); }, hwnd)); | 434 FROM_HERE, BindOnce([](HWND hwnd) { ::DestroyWindow(hwnd); }, hwnd)); |
| 470 | 435 |
| 471 task_tracker_.Shutdown(); | 436 task_tracker_.Shutdown(); |
| 472 } | 437 } |
| 473 | 438 |
| 474 #endif // defined(OS_WIN) | 439 #endif // defined(OS_WIN) |
| 475 | 440 |
| 476 namespace { | 441 namespace { |
| 477 | 442 |
| 478 class TaskSchedulerSingleThreadTaskRunnerManagerStartTest | 443 class TaskSchedulerSingleThreadTaskRunnerManagerStartTest |
| 479 : public TaskSchedulerSingleThreadTaskRunnerManagerTest { | 444 : public TaskSchedulerSingleThreadTaskRunnerManagerTest { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 490 | 455 |
| 491 } // namespace | 456 } // namespace |
| 492 | 457 |
| 493 // Verify that a task posted before Start() doesn't run until Start() is called. | 458 // Verify that a task posted before Start() doesn't run until Start() is called. |
| 494 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerStartTest, | 459 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerStartTest, |
| 495 PostTaskBeforeStart) { | 460 PostTaskBeforeStart) { |
| 496 AtomicFlag manager_started; | 461 AtomicFlag manager_started; |
| 497 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, | 462 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, |
| 498 WaitableEvent::InitialState::NOT_SIGNALED); | 463 WaitableEvent::InitialState::NOT_SIGNALED); |
| 499 single_thread_task_runner_manager_ | 464 single_thread_task_runner_manager_ |
| 500 ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()) | 465 ->CreateSingleThreadTaskRunnerWithTraits("A", ThreadPriority::NORMAL, |
| 466 TaskTraits()) |
| 501 ->PostTask( | 467 ->PostTask( |
| 502 FROM_HERE, | 468 FROM_HERE, |
| 503 Bind( | 469 BindOnce( |
| 504 [](WaitableEvent* task_running, AtomicFlag* manager_started) { | 470 [](WaitableEvent* task_running, AtomicFlag* manager_started) { |
| 505 task_running->Signal(); | 471 task_running->Signal(); |
| 506 | 472 |
| 507 // The task should not run before Start(). | 473 // The task should not run before Start(). |
| 508 EXPECT_TRUE(manager_started->IsSet()); | 474 EXPECT_TRUE(manager_started->IsSet()); |
| 509 }, | 475 }, |
| 510 Unretained(&task_running), Unretained(&manager_started))); | 476 Unretained(&task_running), Unretained(&manager_started))); |
| 511 | 477 |
| 512 // Wait a little bit to make sure that the task isn't scheduled before start. | 478 // Wait a little bit to make sure that the task isn't scheduled before start. |
| 513 // Note: This test won't catch a case where the task is scheduled between | 479 // Note: This test won't catch a case where the task is scheduled between |
| 514 // setting |manager_started| and calling Start(). However, we expect the test | 480 // setting |manager_started| and calling Start(). However, we expect the test |
| 515 // to be flaky if the tested code allows that to happen. | 481 // to be flaky if the tested code allows that to happen. |
| 516 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); | 482 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 517 manager_started.Set(); | 483 manager_started.Set(); |
| 518 single_thread_task_runner_manager_->Start(); | 484 single_thread_task_runner_manager_->Start(); |
| 519 | 485 |
| 520 // This should not hang if the task is scheduled after Start(). | 486 // This should not hang if the task is scheduled after Start(). |
| 521 task_running.Wait(); | 487 task_running.Wait(); |
| 522 } | 488 } |
| 523 | 489 |
| 524 } // namespace internal | 490 } // namespace internal |
| 525 } // namespace base | 491 } // namespace base |
| OLD | NEW |