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