// Copyright 2023 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/logging.h" #include "base/message_loop/message_pump.h" #include "base/rand_util.h" #include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/task/sequence_manager/sequence_manager.h" #include "base/task/sequence_manager/task_queue.h" #include "base/task/single_thread_task_runner.h" enum class TaskType : unsigned char { kSource1 = 1, }; void Task(base::StringPiece tq, int task_number) { if (tq == "A") { LOG(INFO) << "TaskQueue(" << tq << "): " << task_number; } else { LOG(INFO) << " TaskQueue(" << tq << "): " << task_number; } } void QuitTask(base::OnceClosure quit_closure) { LOG(INFO) << "Quittin' time!"; std::move(quit_closure).Run(); } int main() { base::PlatformThread::SetName("SchedulingDemoMain"); std::unique_ptr pump = base::MessagePump::Create(base::MessagePumpType::DEFAULT); // Create the main thread's SequenceManager; it will choose at random which of // the two below TaskQueues will be served at each spin of the loop, despite // them being the same priority. std::unique_ptr sequence_manager = base::sequence_manager::CreateSequenceManagerOnCurrentThreadWithPump( std::move(pump), base::sequence_manager::SequenceManager::Settings::Builder() .SetRandomTaskSelectionSeed(base::RandUint64()) .Build()); // Create two same-priority TaskQueues that feed into the main thread's // SequenceManager. base::sequence_manager::TaskQueue::Handle tq_a = sequence_manager->CreateTaskQueue(base::sequence_manager::TaskQueue::Spec( base::sequence_manager::QueueName::TEST_TQ)); base::sequence_manager::TaskQueue::Handle tq_b = sequence_manager->CreateTaskQueue(base::sequence_manager::TaskQueue::Spec( base::sequence_manager::QueueName::TEST2_TQ)); // Get TaskRunners for both TaskQueues. scoped_refptr a_runner_1 = tq_a->CreateTaskRunner(static_cast(TaskType::kSource1)); sequence_manager->SetDefaultTaskRunner(a_runner_1); scoped_refptr b_runner = tq_b->CreateTaskRunner(static_cast(TaskType::kSource1)); base::RunLoop run_loop; // Like the last example, this shows that TaskQueue is the principal unit of // ordering. All non-delayed tasks posted to the same queue run in FIFO order, // but tasks *across* queues in this case run in random order, as directed by // the SequenceManager that multiplexes them. for (int i = 1; i <= 20; ++i) { a_runner_1->PostTask(FROM_HERE, base::BindOnce(&Task, "A", i)); } for (int i = 0; i < 20; ++i) { b_runner->PostTask(FROM_HERE, base::BindOnce(&Task, "B", i)); } a_runner_1->PostDelayedTask(FROM_HERE, base::BindOnce(&QuitTask, run_loop.QuitClosure()), base::Seconds(1)); run_loop.Run(); return 0; }