blob: 338514cde4fdb8233306d725fd07b32aefd09b7c [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2022 The Chromium Authors
Abdias Dagbekpo6148d122022-08-23 17:36:392// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/task/thread_pool/delayed_priority_queue.h"
6
7#include <utility>
8
9#include "base/check_op.h"
10#include "base/memory/ptr_util.h"
11#include "base/stl_util.h"
12
13namespace base::internal {
14
15// A class combining a TaskSource and the delayed_sort_key that determines its
16// position in a DelayedPriorityQueue. Instances are only mutable via
17// take_task_source() which can only be called once and renders its instance
18// invalid after the call.
19class DelayedPriorityQueue::TaskSourceAndDelayedSortKey {
20 public:
21 TaskSourceAndDelayedSortKey() = default;
22 TaskSourceAndDelayedSortKey(scoped_refptr<TaskSource> task_source,
23 const TimeTicks& delayed_sort_key)
24 : task_source_(std::move(task_source)),
25 delayed_sort_key_(delayed_sort_key) {
26 DCHECK(task_source_);
27 }
28 TaskSourceAndDelayedSortKey(const TaskSourceAndDelayedSortKey&) = delete;
29 TaskSourceAndDelayedSortKey& operator=(const TaskSourceAndDelayedSortKey&) =
30 delete;
31
32 // Note: while |task_source_| should always be non-null post-move (i.e. we
33 // shouldn't be moving an invalid TaskSourceAndDelayedSortKey around), there
34 // can't be a DCHECK(task_source_) on moves as IntrusiveHeap moves elements on
35 // pop instead of overwriting them: resulting in the move of a
36 // TaskSourceAndDelayedSortKey with a null |task_source_| in
37 // Transaction::Pop()'s implementation.
38 TaskSourceAndDelayedSortKey(TaskSourceAndDelayedSortKey&& other) = default;
39 TaskSourceAndDelayedSortKey& operator=(TaskSourceAndDelayedSortKey&& other) =
40 default;
41
42 // Extracts |task_source_| from this object. This object is invalid after this
43 // call.
44 scoped_refptr<TaskSource> take_task_source() {
45 DCHECK(task_source_);
46 task_source_->ClearDelayedHeapHandle();
47 return std::move(task_source_);
48 }
49
50 // Compares this TaskSourceAndDelayedSortKey to |other| based on their
51 // respective |delayed_sort_key_|. Used for a max-heap.
52 bool operator<(const TaskSourceAndDelayedSortKey& other) const {
53 return delayed_sort_key_ < other.delayed_sort_key_;
54 }
55
56 // Required by IntrusiveHeap.
57 void SetHeapHandle(const HeapHandle& handle) {
58 DCHECK(task_source_);
59 task_source_->SetDelayedHeapHandle(handle);
60 }
61
62 // Required by IntrusiveHeap.
63 void ClearHeapHandle() {
64 // Ensure |task_source_| is not nullptr, which may be the case if
65 // take_task_source() was called before this.
Peter Kasting134ef9af2024-12-28 02:30:0966 if (task_source_) {
Abdias Dagbekpo6148d122022-08-23 17:36:3967 task_source_->ClearDelayedHeapHandle();
Peter Kasting134ef9af2024-12-28 02:30:0968 }
Abdias Dagbekpo6148d122022-08-23 17:36:3969 }
70
71 // Required by IntrusiveHeap.
72 HeapHandle GetHeapHandle() const {
Peter Kasting134ef9af2024-12-28 02:30:0973 if (task_source_) {
Abdias Dagbekpo6148d122022-08-23 17:36:3974 return task_source_->GetDelayedHeapHandle();
Peter Kasting134ef9af2024-12-28 02:30:0975 }
Abdias Dagbekpo6148d122022-08-23 17:36:3976 return HeapHandle::Invalid();
77 }
78
79 scoped_refptr<TaskSource> task_source() const { return task_source_; }
80
81 TimeTicks delayed_sort_key() const { return delayed_sort_key_; }
82
83 private:
84 scoped_refptr<TaskSource> task_source_;
85 TimeTicks delayed_sort_key_;
86};
87
88DelayedPriorityQueue::DelayedPriorityQueue() = default;
89
90DelayedPriorityQueue::~DelayedPriorityQueue() {
Peter Kasting134ef9af2024-12-28 02:30:0991 if (!is_flush_task_sources_on_destroy_enabled_) {
Abdias Dagbekpo6148d122022-08-23 17:36:3992 return;
Peter Kasting134ef9af2024-12-28 02:30:0993 }
Abdias Dagbekpo6148d122022-08-23 17:36:3994
95 while (!container_.empty()) {
96 auto task_source = PopTaskSource();
97 task_source->ClearForTesting(); // IN-TEST
98 }
99}
100
101DelayedPriorityQueue& DelayedPriorityQueue::operator=(
102 DelayedPriorityQueue&& other) = default;
103
104void DelayedPriorityQueue::Push(scoped_refptr<TaskSource> task_source,
105 TimeTicks task_source_delayed_sort_key) {
106 container_.insert(TaskSourceAndDelayedSortKey(std::move(task_source),
107 task_source_delayed_sort_key));
108}
109
110const TimeTicks DelayedPriorityQueue::PeekDelayedSortKey() const {
111 DCHECK(!IsEmpty());
112 return container_.top().delayed_sort_key();
113}
114
115scoped_refptr<TaskSource> DelayedPriorityQueue::PeekTaskSource() const {
116 DCHECK(!IsEmpty());
117
118 auto& task_source_and_delayed_sort_key = container_.top();
119 return task_source_and_delayed_sort_key.task_source();
120}
121
122scoped_refptr<TaskSource> DelayedPriorityQueue::PopTaskSource() {
123 DCHECK(!IsEmpty());
124
125 auto task_source_and_delayed_sort_key = container_.take_top();
126 scoped_refptr<TaskSource> task_source =
127 task_source_and_delayed_sort_key.take_task_source();
128 return task_source;
129}
130
131scoped_refptr<TaskSource> DelayedPriorityQueue::RemoveTaskSource(
132 scoped_refptr<TaskSource> task_source) {
Peter Kasting134ef9af2024-12-28 02:30:09133 if (IsEmpty()) {
Abdias Dagbekpo6148d122022-08-23 17:36:39134 return nullptr;
Peter Kasting134ef9af2024-12-28 02:30:09135 }
Abdias Dagbekpo6148d122022-08-23 17:36:39