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/lock.h" | 9 #include "base/synchronization/lock.h" |
10 #include "base/synchronization/waitable_event.h" | 10 #include "base/synchronization/waitable_event.h" |
11 #include "base/task_scheduler/delayed_task_manager.h" | 11 #include "base/task_scheduler/delayed_task_manager.h" |
12 #include "base/task_scheduler/post_task.h" | 12 #include "base/task_scheduler/post_task.h" |
13 #include "base/task_scheduler/scheduler_worker_pool_params.h" | 13 #include "base/task_scheduler/scheduler_worker_pool_params.h" |
14 #include "base/task_scheduler/task_tracker.h" | 14 #include "base/task_scheduler/task_tracker.h" |
15 #include "base/task_scheduler/task_traits.h" | 15 #include "base/task_scheduler/task_traits.h" |
16 #include "base/test/test_timeouts.h" | 16 #include "base/test/test_timeouts.h" |
| 17 #include "base/threading/simple_thread.h" |
17 #include "base/threading/thread.h" | 18 #include "base/threading/thread.h" |
18 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
19 | 20 |
20 namespace base { | 21 namespace base { |
21 namespace internal { | 22 namespace internal { |
22 | 23 |
23 namespace { | 24 namespace { |
24 | 25 |
25 enum WorkerPoolType { | 26 enum WorkerPoolType : size_t { |
26 BACKGROUND_WORKER_POOL = 0, | 27 BACKGROUND_WORKER_POOL = 0, |
27 FOREGROUND_WORKER_POOL, | 28 FOREGROUND_WORKER_POOL, |
28 }; | 29 }; |
29 | 30 |
30 static size_t GetThreadPoolIndexForTraits(const TaskTraits& traits) { | 31 static size_t GetThreadPoolIndexForTraits(const TaskTraits& traits) { |
31 return traits.priority() == TaskPriority::BACKGROUND ? BACKGROUND_WORKER_POOL | 32 return traits.priority() == TaskPriority::BACKGROUND ? BACKGROUND_WORKER_POOL |
32 : FOREGROUND_WORKER_POOL; | 33 : FOREGROUND_WORKER_POOL; |
33 } | 34 } |
34 | 35 |
| 36 std::vector<SchedulerWorkerPoolParams> GetParamsVector() { |
| 37 using StandbyThreadPolicy = SchedulerWorkerPoolParams::StandbyThreadPolicy; |
| 38 |
| 39 std::vector<SchedulerWorkerPoolParams> params_vector; |
| 40 |
| 41 DCHECK_EQ(BACKGROUND_WORKER_POOL, params_vector.size()); |
| 42 params_vector.emplace_back("Background", ThreadPriority::BACKGROUND, |
| 43 StandbyThreadPolicy::LAZY, 1U, TimeDelta::Max()); |
| 44 |
| 45 DCHECK_EQ(FOREGROUND_WORKER_POOL, params_vector.size()); |
| 46 params_vector.emplace_back("Foreground", ThreadPriority::NORMAL, |
| 47 StandbyThreadPolicy::LAZY, 1U, TimeDelta::Max()); |
| 48 |
| 49 return params_vector; |
| 50 } |
| 51 |
35 class TaskSchedulerSingleThreadTaskRunnerManagerTest : public testing::Test { | 52 class TaskSchedulerSingleThreadTaskRunnerManagerTest : public testing::Test { |
36 public: | 53 public: |
37 TaskSchedulerSingleThreadTaskRunnerManagerTest() | 54 TaskSchedulerSingleThreadTaskRunnerManagerTest() |
38 : service_thread_("TaskSchedulerServiceThread") {} | 55 : service_thread_("TaskSchedulerServiceThread") {} |
39 | 56 |
40 void SetUp() override { | 57 void SetUp() override { |
41 service_thread_.Start(); | 58 service_thread_.Start(); |
42 | 59 |
43 using StandbyThreadPolicy = SchedulerWorkerPoolParams::StandbyThreadPolicy; | |
44 | |
45 std::vector<SchedulerWorkerPoolParams> params_vector; | |
46 | |
47 ASSERT_EQ(BACKGROUND_WORKER_POOL, params_vector.size()); | |
48 params_vector.emplace_back("Background", ThreadPriority::BACKGROUND, | |
49 StandbyThreadPolicy::LAZY, 1U, TimeDelta::Max()); | |
50 | |
51 ASSERT_EQ(FOREGROUND_WORKER_POOL, params_vector.size()); | |
52 params_vector.emplace_back("Foreground", ThreadPriority::NORMAL, | |
53 StandbyThreadPolicy::LAZY, 1U, TimeDelta::Max()); | |
54 | |
55 delayed_task_manager_ = | 60 delayed_task_manager_ = |
56 MakeUnique<DelayedTaskManager>(service_thread_.task_runner()); | 61 MakeUnique<DelayedTaskManager>(service_thread_.task_runner()); |
57 single_thread_task_runner_manager_ = | 62 single_thread_task_runner_manager_ = |
58 MakeUnique<SchedulerSingleThreadTaskRunnerManager>( | 63 MakeUnique<SchedulerSingleThreadTaskRunnerManager>( |
59 params_vector, Bind(&GetThreadPoolIndexForTraits), &task_tracker_, | 64 GetParamsVector(), Bind(&GetThreadPoolIndexForTraits), |
60 delayed_task_manager_.get()); | 65 &task_tracker_, delayed_task_manager_.get()); |
61 } | 66 } |
62 | 67 |
63 void TearDown() override { | 68 void TearDown() override { |
64 single_thread_task_runner_manager_->JoinForTesting(); | 69 TearDownSingleThreadTaskRunnerManager(); |
65 single_thread_task_runner_manager_.reset(); | |
66 delayed_task_manager_.reset(); | 70 delayed_task_manager_.reset(); |
67 service_thread_.Stop(); | 71 service_thread_.Stop(); |
68 } | 72 } |
69 | 73 |
70 protected: | 74 protected: |
| 75 virtual void TearDownSingleThreadTaskRunnerManager() { |
| 76 single_thread_task_runner_manager_->JoinForTesting(); |
| 77 single_thread_task_runner_manager_.reset(); |
| 78 } |
| 79 |
71 std::unique_ptr<SchedulerSingleThreadTaskRunnerManager> | 80 std::unique_ptr<SchedulerSingleThreadTaskRunnerManager> |
72 single_thread_task_runner_manager_; | 81 single_thread_task_runner_manager_; |
73 TaskTracker task_tracker_; | 82 TaskTracker task_tracker_; |
74 | 83 |
75 private: | 84 private: |
76 Thread service_thread_; | 85 Thread service_thread_; |
77 std::unique_ptr<DelayedTaskManager> delayed_task_manager_; | 86 std::unique_ptr<DelayedTaskManager> delayed_task_manager_; |
78 | 87 |
79 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTest); | 88 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTest); |
80 }; | 89 }; |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 [](scoped_refptr<SingleThreadTaskRunner> task_runner_1, | 252 [](scoped_refptr<SingleThreadTaskRunner> task_runner_1, |
244 scoped_refptr<SingleThreadTaskRunner> task_runner_2) { | 253 scoped_refptr<SingleThreadTaskRunner> task_runner_2) { |
245 EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread()); | 254 EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread()); |
246 EXPECT_TRUE(task_runner_2->RunsTasksOnCurrentThread()); | 255 EXPECT_TRUE(task_runner_2->RunsTasksOnCurrentThread()); |
247 }, | 256 }, |
248 task_runner_1, task_runner_2)); | 257 task_runner_1, task_runner_2)); |
249 | 258 |
250 task_tracker_.Shutdown(); | 259 task_tracker_.Shutdown(); |
251 } | 260 } |
252 | 261 |
| 262 namespace { |
| 263 |
| 264 class CallJoinFromDifferentThread : public SimpleThread { |
| 265 public: |
| 266 CallJoinFromDifferentThread( |
| 267 SchedulerSingleThreadTaskRunnerManager* manager_to_join) |
| 268 : SimpleThread("SchedulerSingleThreadTaskRunnerManagerJoinThread"), |
| 269 manager_to_join_(manager_to_join), |
| 270 run_started_event_(WaitableEvent::ResetPolicy::MANUAL, |
| 271 WaitableEvent::InitialState::NOT_SIGNALED) {} |
| 272 |
| 273 ~CallJoinFromDifferentThread() override = default; |
| 274 |
| 275 void Run() override { |
| 276 run_started_event_.Signal(); |
| 277 manager_to_join_->JoinForTesting(); |
| 278 } |
| 279 |
| 280 void WaitForRunToStart() { run_started_event_.Wait(); } |
| 281 |
| 282 private: |
| 283 SchedulerSingleThreadTaskRunnerManager* const manager_to_join_; |
| 284 WaitableEvent run_started_event_; |
| 285 DISALLOW_COPY_AND_ASSIGN(CallJoinFromDifferentThread); |
| 286 }; |
| 287 |
| 288 class TaskSchedulerSingleThreadTaskRunnerManagerJoinTest |
| 289 : public TaskSchedulerSingleThreadTaskRunnerManagerTest { |
| 290 public: |
| 291 TaskSchedulerSingleThreadTaskRunnerManagerJoinTest() = default; |
| 292 ~TaskSchedulerSingleThreadTaskRunnerManagerJoinTest() override = default; |
| 293 |
| 294 protected: |
| 295 void TearDownSingleThreadTaskRunnerManager() override { |
| 296 // The tests themselves are responsible for calling JoinForTesting(). |
| 297 single_thread_task_runner_manager_.reset(); |
| 298 } |
| 299 |
| 300 private: |
| 301 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest); |
| 302 }; |
| 303 |
| 304 } // namespace |
| 305 |
| 306 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, ConcurrentJoin) { |
| 307 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, |
| 308 WaitableEvent::InitialState::NOT_SIGNALED); |
| 309 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, |
| 310 WaitableEvent::InitialState::NOT_SIGNALED); |
| 311 |
| 312 { |
| 313 auto task_runner = single_thread_task_runner_manager_ |
| 314 ->CreateSingleThreadTaskRunnerWithTraits( |
| 315 TaskTraits().WithBaseSyncPrimitives()); |
| 316 EXPECT_TRUE(task_runner->PostTask( |
| 317 FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&task_running)))); |
| 318 EXPECT_TRUE(task_runner->PostTask( |
| 319 FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&task_blocking)))); |
| 320 } |
| 321 |
| 322 task_running.Wait(); |
| 323 CallJoinFromDifferentThread join_from_different_thread( |
| 324 single_thread_task_runner_manager_.get()); |
| 325 join_from_different_thread.Start(); |
| 326 join_from_different_thread.WaitForRunToStart(); |
| 327 task_blocking.Signal(); |
| 328 join_from_different_thread.Join(); |
| 329 } |
| 330 |
| 331 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, |
| 332 ConcurrentJoinExtraSkippedTask) { |
| 333 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, |
| 334 WaitableEvent::InitialState::NOT_SIGNALED); |
| 335 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, |
| 336 WaitableEvent::InitialState::NOT_SIGNALED); |
| 337 |
| 338 { |
| 339 auto task_runner = single_thread_task_runner_manager_ |
| 340 ->CreateSingleThreadTaskRunnerWithTraits( |
| 341 TaskTraits().WithBaseSyncPrimitives()); |
| 342 EXPECT_TRUE(task_runner->PostTask( |
| 343 FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&task_running)))); |
| 344 EXPECT_TRUE(task_runner->PostTask( |
| 345 FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&task_blocking)))); |
| 346 EXPECT_TRUE(task_runner->PostTask(FROM_HERE, Bind(&DoNothing))); |
| 347 } |
| 348 |
| 349 task_running.Wait(); |
| 350 CallJoinFromDifferentThread join_from_different_thread( |
| 351 single_thread_task_runner_manager_.get()); |
| 352 join_from_different_thread.Start(); |
| 353 join_from_different_thread.WaitForRunToStart(); |
| 354 task_blocking.Signal(); |
| 355 join_from_different_thread.Join(); |
| 356 } |
| 357 |
253 } // namespace internal | 358 } // namespace internal |
254 } // namespace base | 359 } // namespace base |
OLD | NEW |