Chromium Code Reviews| 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" |
| 11 #include "base/synchronization/waitable_event.h" | 11 #include "base/synchronization/waitable_event.h" |
| 12 #include "base/task_scheduler/delayed_task_manager.h" | 12 #include "base/task_scheduler/delayed_task_manager.h" |
| 13 #include "base/task_scheduler/post_task.h" | 13 #include "base/task_scheduler/post_task.h" |
| 14 #include "base/task_scheduler/scheduler_worker_pool_params.h" | 14 #include "base/task_scheduler/scheduler_worker_pool_params.h" |
| 15 #include "base/task_scheduler/task_tracker.h" | 15 #include "base/task_scheduler/task_tracker.h" |
| 16 #include "base/task_scheduler/task_traits.h" | 16 #include "base/task_scheduler/task_traits.h" |
| 17 #include "base/test/gtest_util.h" | |
| 17 #include "base/test/test_timeouts.h" | 18 #include "base/test/test_timeouts.h" |
| 18 #include "base/threading/platform_thread.h" | 19 #include "base/threading/platform_thread.h" |
| 19 #include "base/threading/simple_thread.h" | 20 #include "base/threading/simple_thread.h" |
| 20 #include "base/threading/thread.h" | 21 #include "base/threading/thread.h" |
| 21 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
| 22 | 23 |
| 23 #if defined(OS_WIN) | 24 #if defined(OS_WIN) |
| 24 #include <windows.h> | 25 #include <windows.h> |
| 25 #include <objbase.h> | 26 #include <objbase.h> |
| 26 | 27 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 75 void CaptureThreadRef(PlatformThreadRef* thread_ref) { | 76 void CaptureThreadRef(PlatformThreadRef* thread_ref) { |
| 76 ASSERT_TRUE(thread_ref); | 77 ASSERT_TRUE(thread_ref); |
| 77 *thread_ref = PlatformThread::CurrentRef(); | 78 *thread_ref = PlatformThread::CurrentRef(); |
| 78 } | 79 } |
| 79 | 80 |
| 80 void CaptureThreadPriority(ThreadPriority* thread_priority) { | 81 void CaptureThreadPriority(ThreadPriority* thread_priority) { |
| 81 ASSERT_TRUE(thread_priority); | 82 ASSERT_TRUE(thread_priority); |
| 82 *thread_priority = PlatformThread::GetCurrentThreadPriority(); | 83 *thread_priority = PlatformThread::GetCurrentThreadPriority(); |
| 83 } | 84 } |
| 84 | 85 |
| 86 void CaptureThreadName(std::string* thread_name) { | |
| 87 *thread_name = PlatformThread::GetName(); | |
| 88 } | |
| 89 | |
| 85 void ShouldNotRun() { | 90 void ShouldNotRun() { |
| 86 ADD_FAILURE() << "Ran a task that shouldn't run."; | 91 ADD_FAILURE() << "Ran a task that shouldn't run."; |
| 87 } | 92 } |
| 88 | 93 |
| 89 } // namespace | 94 } // namespace |
| 90 | 95 |
| 91 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, DifferentThreadsUsed) { | 96 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, DifferentThreadsUsed) { |
| 92 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = | 97 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = |
| 93 single_thread_task_runner_manager_ | 98 single_thread_task_runner_manager_ |
| 94 ->CreateSingleThreadTaskRunnerWithTraits( | 99 ->CreateSingleThreadTaskRunnerWithTraits( |
| 95 "A", ThreadPriority::NORMAL, | 100 "A", {TaskShutdownBehavior::BLOCK_SHUTDOWN}, |
| 96 {TaskShutdownBehavior::BLOCK_SHUTDOWN}); | 101 SingleThreadTaskRunnerThreadMode::DEDICATED); |
| 97 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = | 102 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = |
| 98 single_thread_task_runner_manager_ | 103 single_thread_task_runner_manager_ |
| 99 ->CreateSingleThreadTaskRunnerWithTraits( | 104 ->CreateSingleThreadTaskRunnerWithTraits( |
| 100 "B", ThreadPriority::NORMAL, | 105 "B", {TaskShutdownBehavior::BLOCK_SHUTDOWN}, |
| 101 {TaskShutdownBehavior::BLOCK_SHUTDOWN}); | 106 SingleThreadTaskRunnerThreadMode::DEDICATED); |
| 102 | 107 |
| 103 PlatformThreadRef thread_ref_1; | 108 PlatformThreadRef thread_ref_1; |
| 104 task_runner_1->PostTask(FROM_HERE, | 109 task_runner_1->PostTask(FROM_HERE, |
| 105 BindOnce(&CaptureThreadRef, &thread_ref_1)); | 110 BindOnce(&CaptureThreadRef, &thread_ref_1)); |
| 106 PlatformThreadRef thread_ref_2; | 111 PlatformThreadRef thread_ref_2; |
| 107 task_runner_2->PostTask(FROM_HERE, | 112 task_runner_2->PostTask(FROM_HERE, |
| 108 BindOnce(&CaptureThreadRef, &thread_ref_2)); | 113 BindOnce(&CaptureThreadRef, &thread_ref_2)); |
| 109 | 114 |
| 110 task_tracker_.Shutdown(); | 115 task_tracker_.Shutdown(); |
| 111 | 116 |
| 112 ASSERT_FALSE(thread_ref_1.is_null()); | 117 ASSERT_FALSE(thread_ref_1.is_null()); |
| 113 ASSERT_FALSE(thread_ref_2.is_null()); | 118 ASSERT_FALSE(thread_ref_2.is_null()); |
| 114 EXPECT_NE(thread_ref_1, thread_ref_2); | 119 EXPECT_NE(thread_ref_1, thread_ref_2); |
| 115 } | 120 } |
| 116 | 121 |
| 117 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PrioritySetCorrectly) { | 122 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, SameThreadUsed) { |
| 123 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = | |
| 124 single_thread_task_runner_manager_ | |
| 125 ->CreateSingleThreadTaskRunnerWithTraits( | |
| 126 "A", {TaskShutdownBehavior::BLOCK_SHUTDOWN}, | |
| 127 SingleThreadTaskRunnerThreadMode::SHARED); | |
| 128 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = | |
| 129 single_thread_task_runner_manager_ | |
| 130 ->CreateSingleThreadTaskRunnerWithTraits( | |
| 131 "B", {TaskShutdownBehavior::BLOCK_SHUTDOWN}, | |
| 132 SingleThreadTaskRunnerThreadMode::SHARED); | |
| 133 | |
| 134 PlatformThreadRef thread_ref_1; | |
| 135 task_runner_1->PostTask(FROM_HERE, | |
| 136 BindOnce(&CaptureThreadRef, &thread_ref_1)); | |
| 137 PlatformThreadRef thread_ref_2; | |
| 138 task_runner_2->PostTask(FROM_HERE, | |
| 139 BindOnce(&CaptureThreadRef, &thread_ref_2)); | |
| 140 | |
| 141 task_tracker_.Shutdown(); | |
| 142 | |
| 143 ASSERT_FALSE(thread_ref_1.is_null()); | |
| 144 ASSERT_FALSE(thread_ref_2.is_null()); | |
| 145 EXPECT_EQ(thread_ref_1, thread_ref_2); | |
| 146 } | |
| 147 | |
| 148 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, | |
| 149 RunsTasksOnCurrentThread) { | |
|
gab
2017/05/25 18:47:00
This test should work in both modes, parametrize a
robliao
2017/05/30 20:01:07
Since we do check the thread handle for the COM ca
| |
| 150 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = | |
| 151 single_thread_task_runner_manager_ | |
| 152 ->CreateSingleThreadTaskRunnerWithTraits( | |
| 153 "A", {TaskShutdownBehavior::BLOCK_SHUTDOWN}, | |
| 154 SingleThreadTaskRunnerThreadMode::DEDICATED); | |
| 155 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = | |
| 156 single_thread_task_runner_manager_ | |
| 157 ->CreateSingleThreadTaskRunnerWithTraits( | |
| 158 "B", {TaskShutdownBehavior::BLOCK_SHUTDOWN}, | |
| 159 SingleThreadTaskRunnerThreadMode::DEDICATED); | |
| 160 | |
| 161 EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread()); | |
| 162 EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread()); | |
| 163 | |
| 164 task_runner_1->PostTask( | |
| 165 FROM_HERE, BindOnce( | |
| 166 [](scoped_refptr<SingleThreadTaskRunner> task_runner_1, | |
| 167 scoped_refptr<SingleThreadTaskRunner> task_runner_2) { | |
| 168 EXPECT_TRUE(task_runner_1->RunsTasksOnCurrentThread()); | |
| 169 EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread()); | |
| 170 }, | |
| 171 task_runner_1, task_runner_2)); | |
| 172 | |
| 173 task_runner_2->PostTask( | |
| 174 FROM_HERE, BindOnce( | |
| 175 [](scoped_refptr<SingleThreadTaskRunner> task_runner_1, | |
| 176 scoped_refptr<SingleThreadTaskRunner> task_runner_2) { | |
| 177 EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread()); | |
| 178 EXPECT_TRUE(task_runner_2->RunsTasksOnCurrentThread()); | |
| 179 }, | |
| 180 task_runner_1, task_runner_2)); | |
| 181 | |
| 182 task_tracker_.Shutdown(); | |
| 183 } | |
| 184 | |
| 185 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, | |
| 186 SharedWithBaseSyncPrimitivesDCHECKs) { | |
| 187 EXPECT_DCHECK_DEATH({ | |
| 188 single_thread_task_runner_manager_->CreateSingleThreadTaskRunnerWithTraits( | |
| 189 "A", {WithBaseSyncPrimitives()}, | |
| 190 SingleThreadTaskRunnerThreadMode::SHARED); | |
| 191 }); | |
| 192 } | |
| 193 | |
| 194 namespace { | |
| 195 | |
| 196 class TaskSchedulerSingleThreadTaskRunnerManagerCommonTest | |
| 197 : public TaskSchedulerSingleThreadTaskRunnerManagerTest, | |
| 198 public ::testing::WithParamInterface<SingleThreadTaskRunnerThreadMode> { | |
| 199 public: | |
| 200 TaskSchedulerSingleThreadTaskRunnerManagerCommonTest() = default; | |
| 201 | |
| 202 private: | |
| 203 DISALLOW_COPY_AND_ASSIGN( | |
| 204 TaskSchedulerSingleThreadTaskRunnerManagerCommonTest); | |
| 205 }; | |
| 206 | |
| 207 } // namespace | |
| 208 | |
| 209 TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, | |
| 210 PrioritySetCorrectly) { | |
| 118 // Why are events used here instead of the task tracker? | 211 // 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 | 212 // Shutting down can cause priorities to get raised. This means we have to use |
| 120 // events to determine when a task is run. | 213 // events to determine when a task is run. |
| 121 scoped_refptr<SingleThreadTaskRunner> task_runner_background = | 214 scoped_refptr<SingleThreadTaskRunner> task_runner_background = |
| 122 single_thread_task_runner_manager_ | 215 single_thread_task_runner_manager_ |
| 123 ->CreateSingleThreadTaskRunnerWithTraits("Background", | 216 ->CreateSingleThreadTaskRunnerWithTraits( |
| 124 ThreadPriority::BACKGROUND, | 217 "Background", {TaskPriority::BACKGROUND}, GetParam()); |
| 125 {TaskPriority::BACKGROUND}); | |
| 126 scoped_refptr<SingleThreadTaskRunner> task_runner_normal = | 218 scoped_refptr<SingleThreadTaskRunner> task_runner_normal = |
| 127 single_thread_task_runner_manager_ | 219 single_thread_task_runner_manager_ |
| 128 ->CreateSingleThreadTaskRunnerWithTraits( | 220 ->CreateSingleThreadTaskRunnerWithTraits( |
| 129 "Normal", ThreadPriority::NORMAL, {TaskPriority::USER_VISIBLE}); | 221 "Normal", {TaskPriority::USER_VISIBLE}, GetParam()); |
| 130 | 222 |
| 131 ThreadPriority thread_priority_background; | 223 ThreadPriority thread_priority_background; |
| 132 task_runner_background->PostTask( | 224 task_runner_background->PostTask( |
| 133 FROM_HERE, BindOnce(&CaptureThreadPriority, &thread_priority_background)); | 225 FROM_HERE, BindOnce(&CaptureThreadPriority, &thread_priority_background)); |
| 134 WaitableEvent waitable_event_background( | 226 WaitableEvent waitable_event_background( |
| 135 WaitableEvent::ResetPolicy::MANUAL, | 227 WaitableEvent::ResetPolicy::MANUAL, |
| 136 WaitableEvent::InitialState::NOT_SIGNALED); | 228 WaitableEvent::InitialState::NOT_SIGNALED); |
| 137 task_runner_background->PostTask( | 229 task_runner_background->PostTask( |
| 138 FROM_HERE, | 230 FROM_HERE, |
| 139 BindOnce(&WaitableEvent::Signal, Unretained(&waitable_event_background))); | 231 BindOnce(&WaitableEvent::Signal, Unretained(&waitable_event_background))); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 151 waitable_event_background.Wait(); | 243 waitable_event_background.Wait(); |
| 152 waitable_event_normal.Wait(); | 244 waitable_event_normal.Wait(); |
| 153 | 245 |
| 154 if (Lock::HandlesMultipleThreadPriorities()) | 246 if (Lock::HandlesMultipleThreadPriorities()) |
| 155 EXPECT_EQ(ThreadPriority::BACKGROUND, thread_priority_background); | 247 EXPECT_EQ(ThreadPriority::BACKGROUND, thread_priority_background); |
| 156 else | 248 else |
| 157 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_background); | 249 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_background); |
| 158 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_normal); | 250 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_normal); |
| 159 } | 251 } |
| 160 | 252 |
| 161 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PostTaskAfterShutdown) { | 253 TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, ThreadNamesSet) { |
| 254 constexpr TaskTraits foo_traits = {TaskPriority::BACKGROUND, | |
| 255 TaskShutdownBehavior::BLOCK_SHUTDOWN}; | |
| 256 scoped_refptr<SingleThreadTaskRunner> foo_task_runner = | |
| 257 single_thread_task_runner_manager_ | |
| 258 ->CreateSingleThreadTaskRunnerWithTraits("MyName", foo_traits, | |
| 259 GetParam()); | |
| 260 std::string foo_captured_name; | |
| 261 foo_task_runner->PostTask(FROM_HERE, | |
| 262 BindOnce(&CaptureThreadName, &foo_captured_name)); | |
| 263 | |
| 264 constexpr TaskTraits user_blocking_traits = { | |
| 265 TaskPriority::USER_BLOCKING, MayBlock(), | |
| 266 TaskShutdownBehavior::BLOCK_SHUTDOWN}; | |
| 267 scoped_refptr<SingleThreadTaskRunner> user_blocking_task_runner = | |
| 268 single_thread_task_runner_manager_ | |
| 269 ->CreateSingleThreadTaskRunnerWithTraits("A", user_blocking_traits, | |
| 270 GetParam()); | |
| 271 | |
| 272 std::string user_blocking_captured_name; | |
| 273 user_blocking_task_runner->PostTask( | |
| 274 FROM_HERE, BindOnce(&CaptureThreadName, &user_blocking_captured_name)); | |
| 275 | |
| 276 task_tracker_.Shutdown(); | |
| 277 | |
| 278 EXPECT_NE(std::string::npos, foo_captured_name.find("MyName")); | |
| 279 EXPECT_NE(std::string::npos, | |
| 280 foo_captured_name.find( | |
| 281 kEnvironmentParams[GetEnvironmentIndexForTraits(foo_traits)] | |
| 282 .name_suffix)); | |
| 283 EXPECT_NE( | |
| 284 std::string::npos, | |
| 285 user_blocking_captured_name.find( | |
| 286 kEnvironmentParams[GetEnvironmentIndexForTraits(user_blocking_traits)] | |
| 287 .name_suffix)); | |
| 288 | |
| 289 if (GetParam() == SingleThreadTaskRunnerThreadMode::DEDICATED) { | |
| 290 EXPECT_EQ(std::string::npos, foo_captured_name.find("Shared")); | |
| 291 EXPECT_EQ(std::string::npos, user_blocking_captured_name.find("Shared")); | |
| 292 } else { | |
| 293 EXPECT_NE(std::string::npos, foo_captured_name.find("Shared")); | |
| 294 EXPECT_NE(std::string::npos, user_blocking_captured_name.find("Shared")); | |
| 295 } | |
| 296 } | |
| 297 | |
| 298 TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, | |
| 299 PostTaskAfterShutdown) { | |
| 162 auto task_runner = single_thread_task_runner_manager_ | 300 auto task_runner = single_thread_task_runner_manager_ |
| 163 ->CreateSingleThreadTaskRunnerWithTraits( | 301 ->CreateSingleThreadTaskRunnerWithTraits( |
| 164 "A", ThreadPriority::NORMAL, TaskTraits()); | 302 "A", TaskTraits(), GetParam()); |
| 165 task_tracker_.Shutdown(); | 303 task_tracker_.Shutdown(); |
| 166 EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun))); | 304 EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun))); |
| 167 } | 305 } |
| 168 | 306 |
| 169 // Verify that a Task runs shortly after its delay expires. | 307 // Verify that a Task runs shortly after its delay expires. |
| 170 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PostDelayedTask) { | 308 TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, PostDelayedTask) { |
| 171 TimeTicks start_time = TimeTicks::Now(); | 309 TimeTicks start_time = TimeTicks::Now(); |
| 172 | 310 |
| 173 // Post a task with a short delay. | 311 // Post a task with a short delay. |
| 174 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, | 312 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, |
| 175 WaitableEvent::InitialState::NOT_SIGNALED); | 313 WaitableEvent::InitialState::NOT_SIGNALED); |
| 176 auto task_runner = single_thread_task_runner_manager_ | 314 auto task_runner = single_thread_task_runner_manager_ |
| 177 ->CreateSingleThreadTaskRunnerWithTraits( | 315 ->CreateSingleThreadTaskRunnerWithTraits( |
| 178 "A", ThreadPriority::NORMAL, TaskTraits()); | 316 "A", TaskTraits(), GetParam()); |
| 179 EXPECT_TRUE(task_runner->PostDelayedTask( | 317 EXPECT_TRUE(task_runner->PostDelayedTask( |
| 180 FROM_HERE, BindOnce(&WaitableEvent::Signal, Unretained(&task_ran)), | 318 FROM_HERE, BindOnce(&WaitableEvent::Signal, Unretained(&task_ran)), |
| 181 TestTimeouts::tiny_timeout())); | 319 TestTimeouts::tiny_timeout())); |
| 182 | 320 |
| 183 // Wait until the task runs. | 321 // Wait until the task runs. |
| 184 task_ran.Wait(); | 322 task_ran.Wait(); |
| 185 | 323 |
| 186 // Expect the task to run after its delay expires, but not more than 250 ms | 324 // Expect the task to run after its delay expires, but not more than 250 ms |
| 187 // after that. | 325 // after that. |
| 188 const TimeDelta actual_delay = TimeTicks::Now() - start_time; | 326 const TimeDelta actual_delay = TimeTicks::Now() - start_time; |
| 189 EXPECT_GE(actual_delay, TestTimeouts::tiny_timeout()); | 327 EXPECT_GE(actual_delay, TestTimeouts::tiny_timeout()); |
| 190 EXPECT_LT(actual_delay, | 328 EXPECT_LT(actual_delay, |
| 191 TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout()); | 329 TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout()); |
| 192 } | 330 } |
| 193 | 331 |
| 194 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, | 332 INSTANTIATE_TEST_CASE_P( |
| 195 RunsTasksOnCurrentThread) { | 333 AllModes, |
|
gab
2017/05/25 18:47:01
Should stay here as a Common test, no?
robliao
2017/05/30 20:01:07
See above.
| |
| 196 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = | 334 TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, |
| 197 single_thread_task_runner_manager_ | 335 ::testing::Values(SingleThreadTaskRunnerThreadMode::SHARED, |
| 198 ->CreateSingleThreadTaskRunnerWithTraits( | 336 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 | 337 |
| 231 namespace { | 338 namespace { |
| 232 | 339 |
| 233 class CallJoinFromDifferentThread : public SimpleThread { | 340 class CallJoinFromDifferentThread : public SimpleThread { |
| 234 public: | 341 public: |
| 235 CallJoinFromDifferentThread( | 342 CallJoinFromDifferentThread( |
| 236 SchedulerSingleThreadTaskRunnerManager* manager_to_join) | 343 SchedulerSingleThreadTaskRunnerManager* manager_to_join) |
| 237 : SimpleThread("SchedulerSingleThreadTaskRunnerManagerJoinThread"), | 344 : SimpleThread("SchedulerSingleThreadTaskRunnerManagerJoinThread"), |
| 238 manager_to_join_(manager_to_join), | 345 manager_to_join_(manager_to_join), |
| 239 run_started_event_(WaitableEvent::ResetPolicy::MANUAL, | 346 run_started_event_(WaitableEvent::ResetPolicy::MANUAL, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 275 | 382 |
| 276 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, ConcurrentJoin) { | 383 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, ConcurrentJoin) { |
| 277 // Exercises the codepath where the workers are unavailable for unregistration | 384 // Exercises the codepath where the workers are unavailable for unregistration |
| 278 // because of a Join call. | 385 // because of a Join call. |
| 279 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, | 386 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, |
| 280 WaitableEvent::InitialState::NOT_SIGNALED); | 387 WaitableEvent::InitialState::NOT_SIGNALED); |
| 281 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, | 388 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, |
| 282 WaitableEvent::InitialState::NOT_SIGNALED); | 389 WaitableEvent::InitialState::NOT_SIGNALED); |
| 283 | 390 |
| 284 { | 391 { |
| 285 auto task_runner = | 392 auto task_runner = single_thread_task_runner_manager_ |
| 286 single_thread_task_runner_manager_ | 393 ->CreateSingleThreadTaskRunnerWithTraits( |
| 287 ->CreateSingleThreadTaskRunnerWithTraits( | 394 "A", {WithBaseSyncPrimitives()}, |
| 288 "A", ThreadPriority::NORMAL, {WithBaseSyncPrimitives()}); | 395 SingleThreadTaskRunnerThreadMode::DEDICATED); |
| 289 EXPECT_TRUE(task_runner->PostTask( | 396 EXPECT_TRUE(task_runner->PostTask( |
| 290 FROM_HERE, | 397 FROM_HERE, |
| 291 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); | 398 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); |
| 292 EXPECT_TRUE(task_runner->PostTask( | 399 EXPECT_TRUE(task_runner->PostTask( |
| 293 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); | 400 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); |
| 294 } | 401 } |
| 295 | 402 |
| 296 task_running.Wait(); | 403 task_running.Wait(); |
| 297 CallJoinFromDifferentThread join_from_different_thread( | 404 CallJoinFromDifferentThread join_from_different_thread( |
| 298 single_thread_task_runner_manager_.get()); | 405 single_thread_task_runner_manager_.get()); |
| 299 join_from_different_thread.Start(); | 406 join_from_different_thread.Start(); |
| 300 join_from_different_thread.WaitForRunToStart(); | 407 join_from_different_thread.WaitForRunToStart(); |
| 301 task_blocking.Signal(); | 408 task_blocking.Signal(); |
| 302 join_from_different_thread.Join(); | 409 join_from_different_thread.Join(); |
| 303 } | 410 } |
| 304 | 411 |
| 305 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, | 412 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, |
| 306 ConcurrentJoinExtraSkippedTask) { | 413 ConcurrentJoinExtraSkippedTask) { |
| 307 // Tests to make sure that tasks are properly cleaned up at Join, allowing | 414 // Tests to make sure that tasks are properly cleaned up at Join, allowing |
| 308 // SingleThreadTaskRunners to unregister themselves. | 415 // SingleThreadTaskRunners to unregister themselves. |
| 309 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, | 416 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, |
| 310 WaitableEvent::InitialState::NOT_SIGNALED); | 417 WaitableEvent::InitialState::NOT_SIGNALED); |
| 311 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, | 418 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, |
| 312 WaitableEvent::InitialState::NOT_SIGNALED); | 419 WaitableEvent::InitialState::NOT_SIGNALED); |
| 313 | 420 |
| 314 { | 421 { |
| 315 auto task_runner = | 422 auto task_runner = single_thread_task_runner_manager_ |
| 316 single_thread_task_runner_manager_ | 423 ->CreateSingleThreadTaskRunnerWithTraits( |
| 317 ->CreateSingleThreadTaskRunnerWithTraits( | 424 "A", {WithBaseSyncPrimitives()}, |
| 318 "A", ThreadPriority::NORMAL, {WithBaseSyncPrimitives()}); | 425 SingleThreadTaskRunnerThreadMode::DEDICATED); |
| 319 EXPECT_TRUE(task_runner->PostTask( | 426 EXPECT_TRUE(task_runner->PostTask( |
| 320 FROM_HERE, | 427 FROM_HERE, |
| 321 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); | 428 BindOnce(&WaitableEvent::Signal, Unretained(&task_running)))); |
| 322 EXPECT_TRUE(task_runner->PostTask( | 429 EXPECT_TRUE(task_runner->PostTask( |
| 323 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); | 430 FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking)))); |
| 324 EXPECT_TRUE(task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing))); | 431 EXPECT_TRUE(task_runner->PostTask(FROM_HERE, BindOnce(&DoNothing))); |
| 325 } | 432 } |
| 326 | 433 |
| 327 task_running.Wait(); | 434 task_running.Wait(); |
| 328 CallJoinFromDifferentThread join_from_different_thread( | 435 CallJoinFromDifferentThread join_from_different_thread( |
| 329 single_thread_task_runner_manager_.get()); | 436 single_thread_task_runner_manager_.get()); |
| 330 join_from_different_thread.Start(); | 437 join_from_different_thread.Start(); |
| 331 join_from_different_thread.WaitForRunToStart(); | 438 join_from_different_thread.WaitForRunToStart(); |
| 332 task_blocking.Signal(); | 439 task_blocking.Signal(); |
| 333 join_from_different_thread.Join(); | 440 join_from_different_thread.Join(); |
| 334 } | 441 } |
| 335 | 442 |
| 336 #if defined(OS_WIN) | 443 #if defined(OS_WIN) |
| 337 | 444 |
| 338 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, COMSTAInitialized) { | 445 TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, |
| 446 COMSTAInitialized) { | |
| 339 scoped_refptr<SingleThreadTaskRunner> com_task_runner = | 447 scoped_refptr<SingleThreadTaskRunner> com_task_runner = |
| 340 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( | 448 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( |
| 341 "A", ThreadPriority::NORMAL, {TaskShutdownBehavior::BLOCK_SHUTDOWN}); | 449 "A", {TaskShutdownBehavior::BLOCK_SHUTDOWN}, GetParam()); |
| 342 | 450 |
| 343 com_task_runner->PostTask( | 451 com_task_runner->PostTask( |
| 344 FROM_HERE, BindOnce([]() { | 452 FROM_HERE, BindOnce([]() { |
| 345 HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); | 453 HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); |
| 346 if (SUCCEEDED(hr)) { | 454 if (SUCCEEDED(hr)) { |
| 347 ADD_FAILURE() << "COM STA was not initialized on this thread"; | 455 ADD_FAILURE() << "COM STA was not initialized on this thread"; |
| 348 CoUninitialize(); | 456 CoUninitialize(); |
| 349 } | 457 } |
| 350 })); | 458 })); |
| 351 | 459 |
| 352 task_tracker_.Shutdown(); | 460 task_tracker_.Shutdown(); |
| 353 } | 461 } |
| 354 | 462 |
| 463 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, COMSTASameThreadUsed) { | |
|
gab
2017/05/25 18:47:01
Seems like this is testing an implementation detai
robliao
2017/05/30 20:01:07
This is currently the only reasonable way to verif
| |
| 464 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = | |
| 465 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( | |
| 466 "A", {TaskShutdownBehavior::BLOCK_SHUTDOWN}, | |
| 467 SingleThreadTaskRunnerThreadMode::SHARED); | |
| 468 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = | |
| 469 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( | |
| 470 "B", {TaskShutdownBehavior::BLOCK_SHUTDOWN}, | |
| 471 SingleThreadTaskRunnerThreadMode::SHARED); | |
| 472 | |
| 473 PlatformThreadRef thread_ref_1; | |
| 474 task_runner_1->PostTask(FROM_HERE, | |
| 475 BindOnce(&CaptureThreadRef, &thread_ref_1)); | |
| 476 PlatformThreadRef thread_ref_2; | |
| 477 task_runner_2->PostTask(FROM_HERE, | |
| 478 BindOnce(&CaptureThreadRef, &thread_ref_2)); | |
| 479 | |
| 480 task_tracker_.Shutdown(); | |
| 481 | |
| 482 ASSERT_FALSE(thread_ref_1.is_null()); | |
| 483 ASSERT_FALSE(thread_ref_2.is_null()); | |
| 484 EXPECT_EQ(thread_ref_1, thread_ref_2); | |
| 485 } | |
| 486 | |
| 355 namespace { | 487 namespace { |
| 356 | 488 |
| 357 const wchar_t* const kTestWindowClassName = | 489 const wchar_t* const kTestWindowClassName = |
| 358 L"TaskSchedulerSingleThreadTaskRunnerManagerTestWinMessageWindow"; | 490 L"TaskSchedulerSingleThreadTaskRunnerManagerTestWinMessageWindow"; |
| 359 | 491 |
| 360 class TaskSchedulerSingleThreadTaskRunnerManagerTestWin | 492 class TaskSchedulerSingleThreadTaskRunnerManagerTestWin |
| 361 : public TaskSchedulerSingleThreadTaskRunnerManagerTest { | 493 : public TaskSchedulerSingleThreadTaskRunnerManagerTest { |
| 362 public: | 494 public: |
| 363 TaskSchedulerSingleThreadTaskRunnerManagerTestWin() = default; | 495 TaskSchedulerSingleThreadTaskRunnerManagerTestWin() = default; |
| 364 | 496 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 393 bool register_class_succeeded_ = false; | 525 bool register_class_succeeded_ = false; |
| 394 | 526 |
| 395 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTestWin); | 527 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTestWin); |
| 396 }; | 528 }; |
| 397 | 529 |
| 398 } // namespace | 530 } // namespace |
| 399 | 531 |
| 400 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTestWin, PumpsMessages) { | 532 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTestWin, PumpsMessages) { |
| 401 scoped_refptr<SingleThreadTaskRunner> com_task_runner = | 533 scoped_refptr<SingleThreadTaskRunner> com_task_runner = |
| 402 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( | 534 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( |
| 403 "A", ThreadPriority::NORMAL, {TaskShutdownBehavior::BLOCK_SHUTDOWN}); | 535 "A", {TaskShutdownBehavior::BLOCK_SHUTDOWN}, |
| 536 SingleThreadTaskRunnerThreadMode::DEDICATED); | |
|
gab
2017/05/25 18:47:01
Why isn't this also Common?
robliao
2017/05/30 20:01:07
This uses TaskSchedulerSingleThreadTaskRunnerTestW
| |
| 404 HWND hwnd = nullptr; | 537 HWND hwnd = nullptr; |
| 405 // HWNDs process messages on the thread that created them, so we have to | 538 // 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 | 539 // create them within the context of the task runner to properly simulate a |
| 407 // COM callback. | 540 // COM callback. |
| 408 com_task_runner->PostTask( | 541 com_task_runner->PostTask( |
| 409 FROM_HERE, | 542 FROM_HERE, |
| 410 BindOnce( | 543 BindOnce( |
| 411 [](TaskSchedulerSingleThreadTaskRunnerManagerTestWin* test_harness, | 544 [](TaskSchedulerSingleThreadTaskRunnerManagerTestWin* test_harness, |
| 412 HWND* hwnd) { *hwnd = test_harness->CreateTestWindow(); }, | 545 HWND* hwnd) { *hwnd = test_harness->CreateTestWindow(); }, |
| 413 Unretained(this), &hwnd)); | 546 Unretained(this), &hwnd)); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 439 // Start() is called in the test body rather than in SetUp(). | 572 // Start() is called in the test body rather than in SetUp(). |
| 440 } | 573 } |
| 441 | 574 |
| 442 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerStartTest); | 575 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerStartTest); |
| 443 }; | 576 }; |
| 444 | 577 |
| 445 } // namespace | 578 } // namespace |
| 446 | 579 |
| 447 // Verify that a task posted before Start() doesn't run until Start() is called. | 580 // Verify that a task posted before Start() doesn't run until Start() is called. |
| 448 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerStartTest, | 581 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerStartTest, |
| 449 PostTaskBeforeStart) { | 582 PostTaskBeforeStart) { |
|
gab
2017/05/25 18:47:01
Why isn't this also Common?
robliao
2017/05/30 20:01:07
See above. This is a different class similar to th
| |
| 450 AtomicFlag manager_started; | 583 AtomicFlag manager_started; |
| 451 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, | 584 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, |
| 452 WaitableEvent::InitialState::NOT_SIGNALED); | 585 WaitableEvent::InitialState::NOT_SIGNALED); |
| 453 single_thread_task_runner_manager_ | 586 single_thread_task_runner_manager_ |
| 454 ->CreateSingleThreadTaskRunnerWithTraits("A", ThreadPriority::NORMAL, | 587 ->CreateSingleThreadTaskRunnerWithTraits( |
| 455 TaskTraits()) | 588 "A", TaskTraits(), SingleThreadTaskRunnerThreadMode::DEDICATED) |
| 456 ->PostTask( | 589 ->PostTask( |
| 457 FROM_HERE, | 590 FROM_HERE, |
| 458 BindOnce( | 591 BindOnce( |
| 459 [](WaitableEvent* task_running, AtomicFlag* manager_started) { | 592 [](WaitableEvent* task_running, AtomicFlag* manager_started) { |
| 460 task_running->Signal(); | 593 task_running->Signal(); |
| 461 | 594 |
| 462 // The task should not run before Start(). | 595 // The task should not run before Start(). |
| 463 EXPECT_TRUE(manager_started->IsSet()); | 596 EXPECT_TRUE(manager_started->IsSet()); |
| 464 }, | 597 }, |
| 465 Unretained(&task_running), Unretained(&manager_started))); | 598 Unretained(&task_running), Unretained(&manager_started))); |
| 466 | 599 |
| 467 // Wait a little bit to make sure that the task isn't scheduled before start. | 600 // 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 | 601 // 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 | 602 // setting |manager_started| and calling Start(). However, we expect the test |
| 470 // to be flaky if the tested code allows that to happen. | 603 // to be flaky if the tested code allows that to happen. |
| 471 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); | 604 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 472 manager_started.Set(); | 605 manager_started.Set(); |
| 473 single_thread_task_runner_manager_->Start(); | 606 single_thread_task_runner_manager_->Start(); |
| 474 | 607 |
| 475 // This should not hang if the task is scheduled after Start(). | 608 // This should not hang if the task is scheduled after Start(). |
| 476 task_running.Wait(); | 609 task_running.Wait(); |
| 477 } | 610 } |
| 478 | 611 |
| 479 } // namespace internal | 612 } // namespace internal |
| 480 } // namespace base | 613 } // namespace base |
| OLD | NEW |