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