blob: 5840e1c846e78b472d8dd0d7d94583190ea06525 [file] [log] [blame]
// 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 <string_view>
#include "base/logging.h"
#include "base/message_loop/message_pump.h"
#include "base/rand_util.h"
#include "base/run_loop.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(std::string_view 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<base::MessagePump> 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<base::sequence_manager::SequenceManager> 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<base::SingleThreadTaskRunner> a_runner_1 =
tq_a->CreateTaskRunner(static_cast<int>(TaskType::kSource1));
sequence_manager->SetDefaultTaskRunner(a_runner_1);
scoped_refptr<base::SingleThreadTaskRunner> b_runner =
tq_b->CreateTaskRunner(static_cast<int>(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;
}