#include "base/task/thread_pool/delayed_priority_queue.h"
#include <utility>
#include "base/check_op.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
namespace base::internal {
class DelayedPriorityQueue::TaskSourceAndDelayedSortKey {
public:
TaskSourceAndDelayedSortKey() = default;
TaskSourceAndDelayedSortKey(scoped_refptr<TaskSource> task_source,
const TimeTicks& delayed_sort_key)
: task_source_(std::move(task_source)),
delayed_sort_key_(delayed_sort_key) {
DCHECK(task_source_);
}
TaskSourceAndDelayedSortKey(const TaskSourceAndDelayedSortKey&) = delete;
TaskSourceAndDelayedSortKey& operator=(const TaskSourceAndDelayedSortKey&) =
delete;
TaskSourceAndDelayedSortKey(TaskSourceAndDelayedSortKey&& other) = default;
TaskSourceAndDelayedSortKey& operator=(TaskSourceAndDelayedSortKey&& other) =
default;
scoped_refptr<TaskSource> take_task_source() {
DCHECK(task_source_);
task_source_->ClearDelayedHeapHandle();
return std::move(task_source_);
}
bool operator<(const TaskSourceAndDelayedSortKey& other) const {
return delayed_sort_key_ < other.delayed_sort_key_;
}
void SetHeapHandle(const HeapHandle& handle) {
DCHECK(task_source_);
task_source_->SetDelayedHeapHandle(handle);
}
void ClearHeapHandle() {
if (task_source_) {
task_source_->ClearDelayedHeapHandle();
}
}
HeapHandle GetHeapHandle() const {
if (task_source_) {
return task_source_->GetDelayedHeapHandle();
}
return HeapHandle::Invalid();
}
scoped_refptr<TaskSource> task_source() const { return task_source_; }
TimeTicks delayed_sort_key() const { return delayed_sort_key_; }
private:
scoped_refptr<TaskSource> task_source_;
TimeTicks delayed_sort_key_;
};
DelayedPriorityQueue::DelayedPriorityQueue() = default;
DelayedPriorityQueue::~DelayedPriorityQueue() {
if (!is_flush_task_sources_on_destroy_enabled_) {
return;
}
while (!container_.empty()) {
auto task_source = PopTaskSource();
task_source->ClearForTesting();
}
}
DelayedPriorityQueue& DelayedPriorityQueue::operator=(
DelayedPriorityQueue&& other) = default;
void DelayedPriorityQueue::Push(scoped_refptr<TaskSource> task_source,
TimeTicks task_source_delayed_sort_key) {
container_.insert(TaskSourceAndDelayedSortKey(std::move(task_source),
task_source_delayed_sort_key));
}
const TimeTicks DelayedPriorityQueue::PeekDelayedSortKey() const {
DCHECK(!IsEmpty());
return container_.top().delayed_sort_key();
}
scoped_refptr<TaskSource> DelayedPriorityQueue::PeekTaskSource() const {
DCHECK(!IsEmpty());
auto& task_source_and_delayed_sort_key = container_.top();
return task_source_and_delayed_sort_key.task_source();
}
scoped_refptr<TaskSource> DelayedPriorityQueue::PopTaskSource() {
DCHECK(!IsEmpty());
auto task_source_and_delayed_sort_key = container_.take_top();
scoped_refptr<TaskSource> task_source =
task_source_and_delayed_sort_key.take_task_source();
return task_source;
}
scoped_refptr<TaskSource> DelayedPriorityQueue::RemoveTaskSource(
scoped_refptr<TaskSource> task_source) {
if (IsEmpty()) {
return nullptr;
}
const HeapHandle heap_handle = task_source->delayed_heap_handle();
if (!heap_handle.IsValid()) {
return nullptr;
}
TaskSourceAndDelayedSortKey& task_source_and_delayed_sort_key =
const_cast<DelayedPriorityQueue::TaskSourceAndDelayedSortKey&>(
container_.at(heap_handle));
DCHECK_EQ(task_source_and_delayed_sort_key.task_source(), task_source);
task_source = task_source_and_delayed_sort_key.take_task_source();
container_.erase(heap_handle);
return task_source;
}
void DelayedPriorityQueue::UpdateDelayedSortKey(
scoped_refptr<TaskSource> task_source) {
if (IsEmpty()) {
return;
}
const HeapHandle heap_handle = task_source->delayed_heap_handle();
if (!heap_handle.IsValid()) {
return;
}
DCHECK_EQ(container_.at(heap_handle).task_source(), task_source);
task_source = const_cast<DelayedPriorityQueue::TaskSourceAndDelayedSortKey&>(
container_.at(heap_handle))
.take_task_source();
auto delayed_sort_key = task_source->GetDelayedSortKey();
container_.Replace(
heap_handle,
TaskSourceAndDelayedSortKey(std::move(task_source), delayed_sort_key));
}
bool DelayedPriorityQueue::IsEmpty() const {
return container_.empty();
}
size_t DelayedPriorityQueue::Size() const {
return container_.size();
}
void DelayedPriorityQueue::EnableFlushTaskSourcesOnDestroyForTesting() {
DCHECK(!is_flush_task_sources_on_destroy_enabled_);
is_flush_task_sources_on_destroy_enabled_ = true;
}
bool DelayedPriorityQueue::DelayedPriorityQueueComparisonOperator::operator()(
const TaskSourceAndDelayedSortKey& lhs,
const TaskSourceAndDelayedSortKey& rhs) const {
return lhs.delayed_sort_key() > rhs.delayed_sort_key();
}
}