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