blob: a0f04863ead5dfcb70522a07e3bf1d68ed2e4987 [file] [log] [blame]
// Copyright (c) 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/base/prioritized_task_runner.h"
#include <algorithm>
#include "base/bind.h"
#include "base/task_runner.h"
#include "base/task_runner_util.h"
namespace net {
PrioritizedTaskRunner::Job::Job(const base::Location& from_here,
base::OnceClosure task,
base::OnceClosure reply,
uint32_t priority,
uint32_t task_count)
: from_here(from_here),
task(std::move(task)),
reply(std::move(reply)),
priority(priority),
task_count(task_count) {}
PrioritizedTaskRunner::Job::Job() {}
PrioritizedTaskRunner::Job::~Job() = default;
PrioritizedTaskRunner::Job::Job(Job&& other) = default;
PrioritizedTaskRunner::Job& PrioritizedTaskRunner::Job::operator=(Job&& other) =
default;
PrioritizedTaskRunner::PrioritizedTaskRunner(
scoped_refptr<base::TaskRunner> task_runner)
: task_runner_(std::move(task_runner)) {}
void PrioritizedTaskRunner::PostTaskAndReply(const base::Location& from_here,
base::OnceClosure task,
base::OnceClosure reply,
uint32_t priority) {
Job job(from_here, std::move(task), std::move(reply), priority,
task_count_++);
{
base::AutoLock lock(task_job_heap_lock_);
task_job_heap_.push_back(std::move(job));
std::push_heap(task_job_heap_.begin(), task_job_heap_.end(), JobComparer());
}
task_runner_->PostTaskAndReply(
from_here,
base::BindOnce(&PrioritizedTaskRunner::RunPostTaskAndReply, this),
base::BindOnce(&PrioritizedTaskRunner::RunReply, this));
}
PrioritizedTaskRunner::~PrioritizedTaskRunner() = default;
void PrioritizedTaskRunner::RunPostTaskAndReply() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
// Find the next job to run.
Job job;
{
base::AutoLock lock(task_job_heap_lock_);
std::pop_heap(task_job_heap_.begin(), task_job_heap_.end(), JobComparer());
job = std::move(task_job_heap_.back());
task_job_heap_.pop_back();
}
std::move(job.task).Run();
// Add the job to the reply priority queue.
base::AutoLock reply_lock(reply_job_heap_lock_);
reply_job_heap_.push_back(std::move(job));
std::push_heap(reply_job_heap_.begin(), reply_job_heap_.end(), JobComparer());
}
void PrioritizedTaskRunner::RunReply() {
// Find the next job to run.
Job job;
{
base::AutoLock lock(reply_job_heap_lock_);
std::pop_heap(reply_job_heap_.begin(), reply_job_heap_.end(),
JobComparer());
job = std::move(reply_job_heap_.back());
reply_job_heap_.pop_back();
}
// Run the job.
std::move(job.reply).Run();
}
} // namespace net