xref: /aosp_15_r20/external/cronet/net/base/priority_queue.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef NET_BASE_PRIORITY_QUEUE_H_
6*6777b538SAndroid Build Coastguard Worker #define NET_BASE_PRIORITY_QUEUE_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
9*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include <list>
12*6777b538SAndroid Build Coastguard Worker #include <utility>
13*6777b538SAndroid Build Coastguard Worker #include <vector>
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_checker.h"
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
21*6777b538SAndroid Build Coastguard Worker #include <unordered_set>
22*6777b538SAndroid Build Coastguard Worker #endif
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker namespace net {
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker // A simple priority queue. The order of values is by priority and then FIFO.
27*6777b538SAndroid Build Coastguard Worker // Unlike the std::priority_queue, this implementation allows erasing elements
28*6777b538SAndroid Build Coastguard Worker // from the queue, and all operations are O(p) time for p priority levels.
29*6777b538SAndroid Build Coastguard Worker // The queue is agnostic to priority ordering (whether 0 precedes 1).
30*6777b538SAndroid Build Coastguard Worker // If the highest priority is 0, FirstMin() returns the first in order.
31*6777b538SAndroid Build Coastguard Worker //
32*6777b538SAndroid Build Coastguard Worker // In debug-mode, the internal queues store (id, value) pairs where id is used
33*6777b538SAndroid Build Coastguard Worker // to validate Pointers.
34*6777b538SAndroid Build Coastguard Worker //
35*6777b538SAndroid Build Coastguard Worker template <typename T>
36*6777b538SAndroid Build Coastguard Worker class PriorityQueue {
37*6777b538SAndroid Build Coastguard Worker  private:
38*6777b538SAndroid Build Coastguard Worker   // This section is up-front for Pointer only.
39*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
40*6777b538SAndroid Build Coastguard Worker   typedef std::list<std::pair<unsigned, T> > List;
41*6777b538SAndroid Build Coastguard Worker #else
42*6777b538SAndroid Build Coastguard Worker   typedef std::list<T> List;
43*6777b538SAndroid Build Coastguard Worker #endif
44*6777b538SAndroid Build Coastguard Worker 
45*6777b538SAndroid Build Coastguard Worker  public:
46*6777b538SAndroid Build Coastguard Worker   typedef uint32_t Priority;
47*6777b538SAndroid Build Coastguard Worker 
48*6777b538SAndroid Build Coastguard Worker   // A pointer to a value stored in the queue. The pointer becomes invalid
49*6777b538SAndroid Build Coastguard Worker   // when the queue is destroyed or cleared, or the value is erased.
50*6777b538SAndroid Build Coastguard Worker   class Pointer {
51*6777b538SAndroid Build Coastguard Worker    public:
52*6777b538SAndroid Build Coastguard Worker     // Constructs a null pointer.
Pointer()53*6777b538SAndroid Build Coastguard Worker     Pointer() : priority_(kNullPriority) {
54*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
55*6777b538SAndroid Build Coastguard Worker       id_ = static_cast<unsigned>(-1);
56*6777b538SAndroid Build Coastguard Worker #endif
57*6777b538SAndroid Build Coastguard Worker       // TODO(syzm)
58*6777b538SAndroid Build Coastguard Worker       // An uninitialized iterator behaves like an uninitialized pointer as per
59*6777b538SAndroid Build Coastguard Worker       // the STL docs. The fix below is ugly and should possibly be replaced
60*6777b538SAndroid Build Coastguard Worker       // with a better approach.
61*6777b538SAndroid Build Coastguard Worker       iterator_ = dummy_empty_list_.end();
62*6777b538SAndroid Build Coastguard Worker     }
63*6777b538SAndroid Build Coastguard Worker 
Pointer(const Pointer & p)64*6777b538SAndroid Build Coastguard Worker     Pointer(const Pointer& p)
65*6777b538SAndroid Build Coastguard Worker         : priority_(p.priority_),
66*6777b538SAndroid Build Coastguard Worker           iterator_(p.iterator_) {
67*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
68*6777b538SAndroid Build Coastguard Worker       id_ = p.id_;
69*6777b538SAndroid Build Coastguard Worker #endif
70*6777b538SAndroid Build Coastguard Worker     }
71*6777b538SAndroid Build Coastguard Worker 
72*6777b538SAndroid Build Coastguard Worker     Pointer& operator=(const Pointer& p) {
73*6777b538SAndroid Build Coastguard Worker       // Self-assignment is benign.
74*6777b538SAndroid Build Coastguard Worker       priority_ = p.priority_;
75*6777b538SAndroid Build Coastguard Worker       iterator_ = p.iterator_;
76*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
77*6777b538SAndroid Build Coastguard Worker       id_ = p.id_;
78*6777b538SAndroid Build Coastguard Worker #endif
79*6777b538SAndroid Build Coastguard Worker       return *this;
80*6777b538SAndroid Build Coastguard Worker     }
81*6777b538SAndroid Build Coastguard Worker 
is_null()82*6777b538SAndroid Build Coastguard Worker     bool is_null() const { return priority_ == kNullPriority; }
83*6777b538SAndroid Build Coastguard Worker 
priority()84*6777b538SAndroid Build Coastguard Worker     Priority priority() const { return priority_; }
85*6777b538SAndroid Build Coastguard Worker 
86*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
value()87*6777b538SAndroid Build Coastguard Worker     const T& value() const { return iterator_->second; }
88*6777b538SAndroid Build Coastguard Worker #else
value()89*6777b538SAndroid Build Coastguard Worker     const T& value() const { return *iterator_; }
90*6777b538SAndroid Build Coastguard Worker #endif
91*6777b538SAndroid Build Coastguard Worker 
92*6777b538SAndroid Build Coastguard Worker     // Comparing to Pointer from a different PriorityQueue is undefined.
Equals(const Pointer & other)93*6777b538SAndroid Build Coastguard Worker     bool Equals(const Pointer& other) const {
94*6777b538SAndroid Build Coastguard Worker       return (priority_ == other.priority_) && (iterator_ == other.iterator_);
95*6777b538SAndroid Build Coastguard Worker     }
96*6777b538SAndroid Build Coastguard Worker 
Reset()97*6777b538SAndroid Build Coastguard Worker     void Reset() {
98*6777b538SAndroid Build Coastguard Worker       *this = Pointer();
99*6777b538SAndroid Build Coastguard Worker     }
100*6777b538SAndroid Build Coastguard Worker 
101*6777b538SAndroid Build Coastguard Worker    private:
102*6777b538SAndroid Build Coastguard Worker     friend class PriorityQueue;
103*6777b538SAndroid Build Coastguard Worker 
104*6777b538SAndroid Build Coastguard Worker     // Note that we need iterator and not const_iterator to pass to
105*6777b538SAndroid Build Coastguard Worker     // List::erase.  When C++11 is turned on for Chromium, this could
106*6777b538SAndroid Build Coastguard Worker     // be changed to const_iterator and the const_casts in the rest of
107*6777b538SAndroid Build Coastguard Worker     // the file can be removed.
108*6777b538SAndroid Build Coastguard Worker     typedef typename PriorityQueue::List::iterator ListIterator;
109*6777b538SAndroid Build Coastguard Worker 
110*6777b538SAndroid Build Coastguard Worker     static const Priority kNullPriority = static_cast<Priority>(-1);
111*6777b538SAndroid Build Coastguard Worker 
112*6777b538SAndroid Build Coastguard Worker     // It is guaranteed that Pointer will treat |iterator| as a
113*6777b538SAndroid Build Coastguard Worker     // const_iterator.
Pointer(Priority priority,const ListIterator & iterator)114*6777b538SAndroid Build Coastguard Worker     Pointer(Priority priority, const ListIterator& iterator)
115*6777b538SAndroid Build Coastguard Worker         : priority_(priority), iterator_(iterator) {
116*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
117*6777b538SAndroid Build Coastguard Worker       id_ = iterator_->first;
118*6777b538SAndroid Build Coastguard Worker #endif
119*6777b538SAndroid Build Coastguard Worker     }
120*6777b538SAndroid Build Coastguard Worker 
121*6777b538SAndroid Build Coastguard Worker     Priority priority_;
122*6777b538SAndroid Build Coastguard Worker     ListIterator iterator_;
123*6777b538SAndroid Build Coastguard Worker     // The STL iterators when uninitialized are like uninitialized pointers
124*6777b538SAndroid Build Coastguard Worker     // which cause crashes when assigned to other iterators. We need to
125*6777b538SAndroid Build Coastguard Worker     // initialize a NULL iterator to the end of a valid list.
126*6777b538SAndroid Build Coastguard Worker     List dummy_empty_list_;
127*6777b538SAndroid Build Coastguard Worker 
128*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
129*6777b538SAndroid Build Coastguard Worker     // Used by the queue to check if a Pointer is valid.
130*6777b538SAndroid Build Coastguard Worker     unsigned id_;
131*6777b538SAndroid Build Coastguard Worker #endif
132*6777b538SAndroid Build Coastguard Worker   };
133*6777b538SAndroid Build Coastguard Worker 
134*6777b538SAndroid Build Coastguard Worker   // Creates a new queue for |num_priorities|.
PriorityQueue(Priority num_priorities)135*6777b538SAndroid Build Coastguard Worker   explicit PriorityQueue(Priority num_priorities) : lists_(num_priorities) {
136*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
137*6777b538SAndroid Build Coastguard Worker     next_id_ = 0;
138*6777b538SAndroid Build Coastguard Worker #endif
139*6777b538SAndroid Build Coastguard Worker   }
140*6777b538SAndroid Build Coastguard Worker 
141*6777b538SAndroid Build Coastguard Worker   PriorityQueue(const PriorityQueue&) = delete;
142*6777b538SAndroid Build Coastguard Worker   PriorityQueue& operator=(const PriorityQueue&) = delete;
~PriorityQueue()143*6777b538SAndroid Build Coastguard Worker   ~PriorityQueue() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); }
144*6777b538SAndroid Build Coastguard Worker 
145*6777b538SAndroid Build Coastguard Worker   // Adds |value| with |priority| to the queue. Returns a pointer to the
146*6777b538SAndroid Build Coastguard Worker   // created element.
Insert(T value,Priority priority)147*6777b538SAndroid Build Coastguard Worker   Pointer Insert(T value, Priority priority) {
148*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
149*6777b538SAndroid Build Coastguard Worker     DCHECK_LT(priority, lists_.size());
150*6777b538SAndroid Build Coastguard Worker     ++size_;
151*6777b538SAndroid Build Coastguard Worker     List& list = lists_[priority];
152*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
153*6777b538SAndroid Build Coastguard Worker     unsigned id = next_id_;
154*6777b538SAndroid Build Coastguard Worker     valid_ids_.insert(id);
155*6777b538SAndroid Build Coastguard Worker     ++next_id_;
156*6777b538SAndroid Build Coastguard Worker     list.emplace_back(id, std::move(value));
157*6777b538SAndroid Build Coastguard Worker #else
158*6777b538SAndroid Build Coastguard Worker     list.emplace_back(std::move(value));
159*6777b538SAndroid Build Coastguard Worker #endif
160*6777b538SAndroid Build Coastguard Worker     return Pointer(priority, std::prev(list.end()));
161*6777b538SAndroid Build Coastguard Worker   }
162*6777b538SAndroid Build Coastguard Worker 
163*6777b538SAndroid Build Coastguard Worker   // Adds |value| with |priority| to the queue. Returns a pointer to the
164*6777b538SAndroid Build Coastguard Worker   // created element.
InsertAtFront(T value,Priority priority)165*6777b538SAndroid Build Coastguard Worker   Pointer InsertAtFront(T value, Priority priority) {
166*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
167*6777b538SAndroid Build Coastguard Worker     DCHECK_LT(priority, lists_.size());
168*6777b538SAndroid Build Coastguard Worker     ++size_;
169*6777b538SAndroid Build Coastguard Worker     List& list = lists_[priority];
170*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
171*6777b538SAndroid Build Coastguard Worker     unsigned id = next_id_;
172*6777b538SAndroid Build Coastguard Worker     valid_ids_.insert(id);
173*6777b538SAndroid Build Coastguard Worker     ++next_id_;
174*6777b538SAndroid Build Coastguard Worker     list.emplace_front(std::pair(id, std::move(value)));
175*6777b538SAndroid Build Coastguard Worker #else
176*6777b538SAndroid Build Coastguard Worker     list.emplace_front(std::move(value));
177*6777b538SAndroid Build Coastguard Worker #endif
178*6777b538SAndroid Build Coastguard Worker     return Pointer(priority, list.begin());
179*6777b538SAndroid Build Coastguard Worker   }
180*6777b538SAndroid Build Coastguard Worker 
181*6777b538SAndroid Build Coastguard Worker   // Removes the value pointed by |pointer| from the queue. All pointers to this
182*6777b538SAndroid Build Coastguard Worker   // value including |pointer| become invalid. Returns the erased value.
Erase(const Pointer & pointer)183*6777b538SAndroid Build Coastguard Worker   T Erase(const Pointer& pointer) {
184*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
185*6777b538SAndroid Build Coastguard Worker     DCHECK_LT(pointer.priority_, lists_.size());
186*6777b538SAndroid Build Coastguard Worker     DCHECK_GT(size_, 0u);
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
189*6777b538SAndroid Build Coastguard Worker     DCHECK_EQ(1u, valid_ids_.erase(pointer.id_));
190*6777b538SAndroid Build Coastguard Worker     DCHECK_EQ(pointer.iterator_->first, pointer.id_);
191*6777b538SAndroid Build Coastguard Worker     T erased = std::move(pointer.iterator_->second);
192*6777b538SAndroid Build Coastguard Worker #else
193*6777b538SAndroid Build Coastguard Worker     T erased = std::move(*pointer.iterator_);
194*6777b538SAndroid Build Coastguard Worker #endif
195*6777b538SAndroid Build Coastguard Worker 
196*6777b538SAndroid Build Coastguard Worker     --size_;
197*6777b538SAndroid Build Coastguard Worker     lists_[pointer.priority_].erase(pointer.iterator_);
198*6777b538SAndroid Build Coastguard Worker     return erased;
199*6777b538SAndroid Build Coastguard Worker   }
200*6777b538SAndroid Build Coastguard Worker 
201*6777b538SAndroid Build Coastguard Worker   // Returns a pointer to the first value of minimum priority or a null-pointer
202*6777b538SAndroid Build Coastguard Worker   // if empty.
FirstMin()203*6777b538SAndroid Build Coastguard Worker   Pointer FirstMin() const {
204*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
205*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < lists_.size(); ++i) {
206*6777b538SAndroid Build Coastguard Worker       List* list = const_cast<List*>(&lists_[i]);
207*6777b538SAndroid Build Coastguard Worker       if (!list->empty())
208*6777b538SAndroid Build Coastguard Worker         return Pointer(i, list->begin());
209*6777b538SAndroid Build Coastguard Worker     }
210*6777b538SAndroid Build Coastguard Worker     return Pointer();
211*6777b538SAndroid Build Coastguard Worker   }
212*6777b538SAndroid Build Coastguard Worker 
213*6777b538SAndroid Build Coastguard Worker   // Returns a pointer to the last value of minimum priority or a null-pointer
214*6777b538SAndroid Build Coastguard Worker   // if empty.
LastMin()215*6777b538SAndroid Build Coastguard Worker   Pointer LastMin() const {
216*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
217*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < lists_.size(); ++i) {
218*6777b538SAndroid Build Coastguard Worker       List* list = const_cast<List*>(&lists_[i]);
219*6777b538SAndroid Build Coastguard Worker       if (!list->empty())
220*6777b538SAndroid Build Coastguard Worker         return Pointer(i, --list->end());
221*6777b538SAndroid Build Coastguard Worker     }
222*6777b538SAndroid Build Coastguard Worker     return Pointer();
223*6777b538SAndroid Build Coastguard Worker   }
224*6777b538SAndroid Build Coastguard Worker 
225*6777b538SAndroid Build Coastguard Worker   // Returns a pointer to the first value of maximum priority or a null-pointer
226*6777b538SAndroid Build Coastguard Worker   // if empty.
FirstMax()227*6777b538SAndroid Build Coastguard Worker   Pointer FirstMax() const {
228*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
229*6777b538SAndroid Build Coastguard Worker     for (size_t i = lists_.size(); i > 0; --i) {
230*6777b538SAndroid Build Coastguard Worker       size_t index = i - 1;
231*6777b538SAndroid Build Coastguard Worker       List* list = const_cast<List*>(&lists_[index]);
232*6777b538SAndroid Build Coastguard Worker       if (!list->empty())
233*6777b538SAndroid Build Coastguard Worker         return Pointer(index, list->begin());
234*6777b538SAndroid Build Coastguard Worker     }
235*6777b538SAndroid Build Coastguard Worker     return Pointer();
236*6777b538SAndroid Build Coastguard Worker   }
237*6777b538SAndroid Build Coastguard Worker 
238*6777b538SAndroid Build Coastguard Worker   // Returns a pointer to the last value of maximum priority or a null-pointer
239*6777b538SAndroid Build Coastguard Worker   // if empty.
LastMax()240*6777b538SAndroid Build Coastguard Worker   Pointer LastMax() const {
241*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
242*6777b538SAndroid Build Coastguard Worker     for (size_t i = lists_.size(); i > 0; --i) {
243*6777b538SAndroid Build Coastguard Worker       size_t index = i - 1;
244*6777b538SAndroid Build Coastguard Worker       List* list = const_cast<List*>(&lists_[index]);
245*6777b538SAndroid Build Coastguard Worker       if (!list->empty())
246*6777b538SAndroid Build Coastguard Worker         return Pointer(index, --list->end());
247*6777b538SAndroid Build Coastguard Worker     }
248*6777b538SAndroid Build Coastguard Worker     return Pointer();
249*6777b538SAndroid Build Coastguard Worker   }
250*6777b538SAndroid Build Coastguard Worker 
251*6777b538SAndroid Build Coastguard Worker   // Given an ordering of the values in this queue by decreasing priority and
252*6777b538SAndroid Build Coastguard Worker   // then FIFO, returns a pointer to the value following the value of the given
253*6777b538SAndroid Build Coastguard Worker   // pointer (which must be non-NULL). I.e., gets the next element in decreasing
254*6777b538SAndroid Build Coastguard Worker   // priority, then FIFO order. If the given pointer is already pointing at the
255*6777b538SAndroid Build Coastguard Worker   // last value, returns a null Pointer.
256*6777b538SAndroid Build Coastguard Worker   //
257*6777b538SAndroid Build Coastguard Worker   // (One could also implement GetNextTowardsFirstMin() [decreasing priority,
258*6777b538SAndroid Build Coastguard Worker   // then reverse FIFO] as well as GetNextTowards{First,Last}Max() [increasing
259*6777b538SAndroid Build Coastguard Worker   // priority, then {,reverse} FIFO].)
GetNextTowardsLastMin(const Pointer & pointer)260*6777b538SAndroid Build Coastguard Worker   Pointer GetNextTowardsLastMin(const Pointer& pointer) const {
261*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
262*6777b538SAndroid Build Coastguard Worker     DCHECK(!pointer.is_null());
263*6777b538SAndroid Build Coastguard Worker     DCHECK_LT(pointer.priority_, lists_.size());
264*6777b538SAndroid Build Coastguard Worker 
265*6777b538SAndroid Build Coastguard Worker     typename Pointer::ListIterator it = pointer.iterator_;
266*6777b538SAndroid Build Coastguard Worker     Priority priority = pointer.priority_;
267*6777b538SAndroid Build Coastguard Worker     DCHECK(it != lists_[priority].end());
268*6777b538SAndroid Build Coastguard Worker     ++it;
269*6777b538SAndroid Build Coastguard Worker     while (it == lists_[priority].end()) {
270*6777b538SAndroid Build Coastguard Worker       if (priority == 0u) {
271*6777b538SAndroid Build Coastguard Worker         DCHECK(pointer.Equals(LastMin()));
272*6777b538SAndroid Build Coastguard Worker         return Pointer();
273*6777b538SAndroid Build Coastguard Worker       }
274*6777b538SAndroid Build Coastguard Worker       --priority;
275*6777b538SAndroid Build Coastguard Worker       it = const_cast<List*>(&lists_[priority])->begin();
276*6777b538SAndroid Build Coastguard Worker     }
277*6777b538SAndroid Build Coastguard Worker     return Pointer(priority, it);
278*6777b538SAndroid Build Coastguard Worker   }
279*6777b538SAndroid Build Coastguard Worker 
280*6777b538SAndroid Build Coastguard Worker   // Given an ordering of the values in this queue by decreasing priority and
281*6777b538SAndroid Build Coastguard Worker   // then FIFO, returns a pointer to the value preceding the value of the given
282*6777b538SAndroid Build Coastguard Worker   // pointer (which must be non-NULL). I.e., gets the next element in increasing
283*6777b538SAndroid Build Coastguard Worker   // priority, then reverse FIFO order. If the given pointer is already pointing
284*6777b538SAndroid Build Coastguard Worker   // at the first value, returns a null Pointer.
GetPreviousTowardsFirstMax(const Pointer & pointer)285*6777b538SAndroid Build Coastguard Worker   Pointer GetPreviousTowardsFirstMax(const Pointer& pointer) const {
286*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
287*6777b538SAndroid Build Coastguard Worker     DCHECK(!pointer.is_null());
288*6777b538SAndroid Build Coastguard Worker     DCHECK_LT(pointer.priority_, lists_.size());
289*6777b538SAndroid Build Coastguard Worker 
290*6777b538SAndroid Build Coastguard Worker     typename Pointer::ListIterator it = pointer.iterator_;
291*6777b538SAndroid Build Coastguard Worker     Priority priority = pointer.priority_;
292*6777b538SAndroid Build Coastguard Worker     DCHECK(it != lists_[priority].end());
293*6777b538SAndroid Build Coastguard Worker     while (it == lists_[priority].begin()) {
294*6777b538SAndroid Build Coastguard Worker       if (priority == num_priorities() - 1) {
295*6777b538SAndroid Build Coastguard Worker         DCHECK(pointer.Equals(FirstMax()));
296*6777b538SAndroid Build Coastguard Worker         return Pointer();
297*6777b538SAndroid Build Coastguard Worker       }
298*6777b538SAndroid Build Coastguard Worker       ++priority;
299*6777b538SAndroid Build Coastguard Worker       it = const_cast<List*>(&lists_[priority])->end();
300*6777b538SAndroid Build Coastguard Worker     }
301*6777b538SAndroid Build Coastguard Worker     return Pointer(priority, std::prev(it));
302*6777b538SAndroid Build Coastguard Worker   }
303*6777b538SAndroid Build Coastguard Worker 
304*6777b538SAndroid Build Coastguard Worker   // Checks whether |lhs| is closer in the queue to the first max element than
305*6777b538SAndroid Build Coastguard Worker   // |rhs|. Assumes that both Pointers refer to elements in this PriorityQueue.
IsCloserToFirstMaxThan(const Pointer & lhs,const Pointer & rhs)306*6777b538SAndroid Build Coastguard Worker   bool IsCloserToFirstMaxThan(const Pointer& lhs, const Pointer& rhs) {
307*6777b538SAndroid Build Coastguard Worker     if (lhs.Equals(rhs))
308*6777b538SAndroid Build Coastguard Worker       return false;
309*6777b538SAndroid Build Coastguard Worker     if (lhs.priority_ == rhs.priority_) {
310*6777b538SAndroid Build Coastguard Worker       // Traverse list starting from lhs and see if we find rhs.
311*6777b538SAndroid Build Coastguard Worker       for (auto it = lhs.iterator_; it != lists_[lhs.priority_].end(); ++it) {
312*6777b538SAndroid Build Coastguard Worker         if (it == rhs.iterator_)
313*6777b538SAndroid Build Coastguard Worker           return true;
314*6777b538SAndroid Build Coastguard Worker       }
315*6777b538SAndroid Build Coastguard Worker       return false;
316*6777b538SAndroid Build Coastguard Worker     }
317*6777b538SAndroid Build Coastguard Worker     return lhs.priority_ > rhs.priority_;
318*6777b538SAndroid Build Coastguard Worker   }
319*6777b538SAndroid Build Coastguard Worker 
320*6777b538SAndroid Build Coastguard Worker   // Checks whether |lhs| is closer in the queue to the last min element than
321*6777b538SAndroid Build Coastguard Worker   // |rhs|. Assumes that both Pointers refer to elements in this PriorityQueue.
IsCloserToLastMinThan(const Pointer & lhs,const Pointer & rhs)322*6777b538SAndroid Build Coastguard Worker   bool IsCloserToLastMinThan(const Pointer& lhs, const Pointer& rhs) {
323*6777b538SAndroid Build Coastguard Worker     return !lhs.Equals(rhs) && !IsCloserToFirstMaxThan(lhs, rhs);
324*6777b538SAndroid Build Coastguard Worker   }
325*6777b538SAndroid Build Coastguard Worker 
326*6777b538SAndroid Build Coastguard Worker   // Finds the first element (with respect to decreasing priority, then FIFO
327*6777b538SAndroid Build Coastguard Worker   // order) which matches the given predicate.
FindIf(const base::RepeatingCallback<bool (T)> & pred)328*6777b538SAndroid Build Coastguard Worker   Pointer FindIf(const base::RepeatingCallback<bool(T)>& pred) {
329*6777b538SAndroid Build Coastguard Worker     for (auto pointer = FirstMax(); !pointer.is_null();
330*6777b538SAndroid Build Coastguard Worker          pointer = GetNextTowardsLastMin(pointer)) {
331*6777b538SAndroid Build Coastguard Worker       if (pred.Run(pointer.value()))
332*6777b538SAndroid Build Coastguard Worker         return pointer;
333*6777b538SAndroid Build Coastguard Worker     }
334*6777b538SAndroid Build Coastguard Worker     return Pointer();
335*6777b538SAndroid Build Coastguard Worker   }
336*6777b538SAndroid Build Coastguard Worker 
337*6777b538SAndroid Build Coastguard Worker   // Empties the queue. All pointers become invalid.
Clear()338*6777b538SAndroid Build Coastguard Worker   void Clear() {
339*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
340*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < lists_.size(); ++i) {
341*6777b538SAndroid Build Coastguard Worker       lists_[i].clear();
342*6777b538SAndroid Build Coastguard Worker     }
343*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
344*6777b538SAndroid Build Coastguard Worker     valid_ids_.clear();
345*6777b538SAndroid Build Coastguard Worker #endif
346*6777b538SAndroid Build Coastguard Worker     size_ = 0u;
347*6777b538SAndroid Build Coastguard Worker   }
348*6777b538SAndroid Build Coastguard Worker 
349*6777b538SAndroid Build Coastguard Worker   // Returns the number of priorities the queue supports.
num_priorities()350*6777b538SAndroid Build Coastguard Worker   size_t num_priorities() const {
351*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
352*6777b538SAndroid Build Coastguard Worker     return lists_.size();
353*6777b538SAndroid Build Coastguard Worker   }
354*6777b538SAndroid Build Coastguard Worker 
empty()355*6777b538SAndroid Build Coastguard Worker   bool empty() const {
356*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
357*6777b538SAndroid Build Coastguard Worker     return size_ == 0;
358*6777b538SAndroid Build Coastguard Worker   }
359*6777b538SAndroid Build Coastguard Worker 
360*6777b538SAndroid Build Coastguard Worker   // Returns number of queued values.
size()361*6777b538SAndroid Build Coastguard Worker   size_t size() const {
362*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
363*6777b538SAndroid Build Coastguard Worker     return size_;
364*6777b538SAndroid Build Coastguard Worker   }
365*6777b538SAndroid Build Coastguard Worker 
366*6777b538SAndroid Build Coastguard Worker  private:
367*6777b538SAndroid Build Coastguard Worker   typedef std::vector<List> ListVector;
368*6777b538SAndroid Build Coastguard Worker 
369*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
370*6777b538SAndroid Build Coastguard Worker   unsigned next_id_;
371*6777b538SAndroid Build Coastguard Worker   std::unordered_set<unsigned> valid_ids_;
372*6777b538SAndroid Build Coastguard Worker #endif
373*6777b538SAndroid Build Coastguard Worker 
374*6777b538SAndroid Build Coastguard Worker   ListVector lists_;
375*6777b538SAndroid Build Coastguard Worker   size_t size_ = 0;
376*6777b538SAndroid Build Coastguard Worker 
377*6777b538SAndroid Build Coastguard Worker   THREAD_CHECKER(thread_checker_);
378*6777b538SAndroid Build Coastguard Worker };
379*6777b538SAndroid Build Coastguard Worker 
380*6777b538SAndroid Build Coastguard Worker }  // namespace net
381*6777b538SAndroid Build Coastguard Worker 
382*6777b538SAndroid Build Coastguard Worker #endif  // NET_BASE_PRIORITY_QUEUE_H_
383