| Index: base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
|
| diff --git a/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc b/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
|
| index 6db240a743cd85b0f84978cb1483d41075131c66..2439950433ed2c4e2294b551ec0639504d1308d1 100644
|
| --- a/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
|
| +++ b/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
|
| @@ -14,6 +14,7 @@
|
| #include "base/task_scheduler/task_tracker.h"
|
| #include "base/task_scheduler/task_traits.h"
|
| #include "base/test/test_timeouts.h"
|
| +#include "base/threading/simple_thread.h"
|
| #include "base/threading/thread.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| @@ -22,7 +23,7 @@ namespace internal {
|
|
|
| namespace {
|
|
|
| -enum WorkerPoolType {
|
| +enum WorkerPoolType : size_t {
|
| BACKGROUND_WORKER_POOL = 0,
|
| FOREGROUND_WORKER_POOL,
|
| };
|
| @@ -32,6 +33,22 @@ static size_t GetThreadPoolIndexForTraits(const TaskTraits& traits) {
|
| : FOREGROUND_WORKER_POOL;
|
| }
|
|
|
| +std::vector<SchedulerWorkerPoolParams> GetParamsVector() {
|
| + using StandbyThreadPolicy = SchedulerWorkerPoolParams::StandbyThreadPolicy;
|
| +
|
| + std::vector<SchedulerWorkerPoolParams> params_vector;
|
| +
|
| + DCHECK_EQ(BACKGROUND_WORKER_POOL, params_vector.size());
|
| + params_vector.emplace_back("Background", ThreadPriority::BACKGROUND,
|
| + StandbyThreadPolicy::LAZY, 1U, TimeDelta::Max());
|
| +
|
| + DCHECK_EQ(FOREGROUND_WORKER_POOL, params_vector.size());
|
| + params_vector.emplace_back("Foreground", ThreadPriority::NORMAL,
|
| + StandbyThreadPolicy::LAZY, 1U, TimeDelta::Max());
|
| +
|
| + return params_vector;
|
| +}
|
| +
|
| class TaskSchedulerSingleThreadTaskRunnerManagerTest : public testing::Test {
|
| public:
|
| TaskSchedulerSingleThreadTaskRunnerManagerTest()
|
| @@ -40,34 +57,26 @@ class TaskSchedulerSingleThreadTaskRunnerManagerTest : public testing::Test {
|
| void SetUp() override {
|
| service_thread_.Start();
|
|
|
| - using StandbyThreadPolicy = SchedulerWorkerPoolParams::StandbyThreadPolicy;
|
| -
|
| - std::vector<SchedulerWorkerPoolParams> params_vector;
|
| -
|
| - ASSERT_EQ(BACKGROUND_WORKER_POOL, params_vector.size());
|
| - params_vector.emplace_back("Background", ThreadPriority::BACKGROUND,
|
| - StandbyThreadPolicy::LAZY, 1U, TimeDelta::Max());
|
| -
|
| - ASSERT_EQ(FOREGROUND_WORKER_POOL, params_vector.size());
|
| - params_vector.emplace_back("Foreground", ThreadPriority::NORMAL,
|
| - StandbyThreadPolicy::LAZY, 1U, TimeDelta::Max());
|
| -
|
| delayed_task_manager_ =
|
| MakeUnique<DelayedTaskManager>(service_thread_.task_runner());
|
| single_thread_task_runner_manager_ =
|
| MakeUnique<SchedulerSingleThreadTaskRunnerManager>(
|
| - params_vector, Bind(&GetThreadPoolIndexForTraits), &task_tracker_,
|
| - delayed_task_manager_.get());
|
| + GetParamsVector(), Bind(&GetThreadPoolIndexForTraits),
|
| + &task_tracker_, delayed_task_manager_.get());
|
| }
|
|
|
| void TearDown() override {
|
| - single_thread_task_runner_manager_->JoinForTesting();
|
| - single_thread_task_runner_manager_.reset();
|
| + TearDownSingleThreadTaskRunnerManager();
|
| delayed_task_manager_.reset();
|
| service_thread_.Stop();
|
| }
|
|
|
| protected:
|
| + virtual void TearDownSingleThreadTaskRunnerManager() {
|
| + single_thread_task_runner_manager_->JoinForTesting();
|
| + single_thread_task_runner_manager_.reset();
|
| + }
|
| +
|
| std::unique_ptr<SchedulerSingleThreadTaskRunnerManager>
|
| single_thread_task_runner_manager_;
|
| TaskTracker task_tracker_;
|
| @@ -250,5 +259,101 @@ TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest,
|
| task_tracker_.Shutdown();
|
| }
|
|
|
| +namespace {
|
| +
|
| +class CallJoinFromDifferentThread : public SimpleThread {
|
| + public:
|
| + CallJoinFromDifferentThread(
|
| + SchedulerSingleThreadTaskRunnerManager* manager_to_join)
|
| + : SimpleThread("SchedulerSingleThreadTaskRunnerManagerJoinThread"),
|
| + manager_to_join_(manager_to_join),
|
| + run_started_event_(WaitableEvent::ResetPolicy::MANUAL,
|
| + WaitableEvent::InitialState::NOT_SIGNALED) {}
|
| +
|
| + ~CallJoinFromDifferentThread() override = default;
|
| +
|
| + void Run() override {
|
| + run_started_event_.Signal();
|
| + manager_to_join_->JoinForTesting();
|
| + }
|
| +
|
| + void WaitForRunToStart() { run_started_event_.Wait(); }
|
| +
|
| + private:
|
| + SchedulerSingleThreadTaskRunnerManager* const manager_to_join_;
|
| + WaitableEvent run_started_event_;
|
| + DISALLOW_COPY_AND_ASSIGN(CallJoinFromDifferentThread);
|
| +};
|
| +
|
| +class TaskSchedulerSingleThreadTaskRunnerManagerJoinTest
|
| + : public TaskSchedulerSingleThreadTaskRunnerManagerTest {
|
| + public:
|
| + TaskSchedulerSingleThreadTaskRunnerManagerJoinTest() = default;
|
| + ~TaskSchedulerSingleThreadTaskRunnerManagerJoinTest() override = default;
|
| +
|
| + protected:
|
| + void TearDownSingleThreadTaskRunnerManager() override {
|
| + // The tests themselves are responsible for calling JoinForTesting().
|
| + single_thread_task_runner_manager_.reset();
|
| + }
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest);
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, ConcurrentJoin) {
|
| + WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL,
|
| + WaitableEvent::InitialState::NOT_SIGNALED);
|
| + WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL,
|
| + WaitableEvent::InitialState::NOT_SIGNALED);
|
| +
|
| + {
|
| + auto task_runner = single_thread_task_runner_manager_
|
| + ->CreateSingleThreadTaskRunnerWithTraits(
|
| + TaskTraits().WithBaseSyncPrimitives());
|
| + EXPECT_TRUE(task_runner->PostTask(
|
| + FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&task_running))));
|
| + EXPECT_TRUE(task_runner->PostTask(
|
| + FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&task_blocking))));
|
| + }
|
| +
|
| + task_running.Wait();
|
| + CallJoinFromDifferentThread join_from_different_thread(
|
| + single_thread_task_runner_manager_.get());
|
| + join_from_different_thread.Start();
|
| + join_from_different_thread.WaitForRunToStart();
|
| + task_blocking.Signal();
|
| + join_from_different_thread.Join();
|
| +}
|
| +
|
| +TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest,
|
| + ConcurrentJoinExtraSkippedTask) {
|
| + WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL,
|
| + WaitableEvent::InitialState::NOT_SIGNALED);
|
| + WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL,
|
| + WaitableEvent::InitialState::NOT_SIGNALED);
|
| +
|
| + {
|
| + auto task_runner = single_thread_task_runner_manager_
|
| + ->CreateSingleThreadTaskRunnerWithTraits(
|
| + TaskTraits().WithBaseSyncPrimitives());
|
| + EXPECT_TRUE(task_runner->PostTask(
|
| + FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&task_running))));
|
| + EXPECT_TRUE(task_runner->PostTask(
|
| + FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&task_blocking))));
|
| + EXPECT_TRUE(task_runner->PostTask(FROM_HERE, Bind(&DoNothing)));
|
| + }
|
| +
|
| + task_running.Wait();
|
| + CallJoinFromDifferentThread join_from_different_thread(
|
| + single_thread_task_runner_manager_.get());
|
| + join_from_different_thread.Start();
|
| + join_from_different_thread.WaitForRunToStart();
|
| + task_blocking.Signal();
|
| + join_from_different_thread.Join();
|
| +}
|
| +
|
| } // namespace internal
|
| } // namespace base
|
|
|