OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef NET_BASE_PRIORITY_QUEUE_H_ | |
6 #define NET_BASE_PRIORITY_QUEUE_H_ | |
7 #pragma once | |
8 | |
9 #include <list> | |
10 #include <vector> | |
11 | |
12 #include "base/basictypes.h" | |
13 #ifndef NDEBUG | |
14 #include "base/hash_tables.h" | |
15 #endif | |
16 #include "base/logging.h" | |
17 #include "net/base/net_export.h" | |
18 | |
19 namespace net { | |
20 | |
21 // A simple priority queue. The order of values is by priority and then FIFO. | |
22 // Unlike the std::priority_queue, all operations are O(p) time for p priority | |
cbentzel
2012/01/05 18:32:20
This also allows erasing of elements in the queue,
| |
23 // levels. The queue is agnostic to priority ordering (whether 0 precedes 1). | |
24 // If the highest priority is 0, FirstMin() returns the first in order. | |
25 // | |
26 // In debug-mode, the internal queues store (id, value) pairs where id is used | |
27 // to validate Pointers. | |
28 // | |
29 template<typename T> | |
30 class PriorityQueue { | |
cbentzel
2012/01/05 18:32:20
I think this should derive from NonThreadSafe or h
| |
31 public: | |
32 // A pointer to a value stored in the queue. The pointer becomes invalid | |
33 // when the queue is destroyed or the value is erased or moved. | |
cbentzel
2012/01/05 18:32:20
Nit: remove "or moved". There is no direct support
| |
34 class Pointer { | |
35 public: | |
36 // Constructs a null pointer. | |
37 Pointer() : priority_(kNullPriority) {} | |
38 | |
39 bool is_null() const { return priority_ == kNullPriority; } | |
40 | |
41 size_t priority() const { return priority_; } | |
cbentzel
2012/01/05 18:32:20
I'd argue for just using uint32 rather than a size
| |
42 | |
43 #ifndef NDEBUG | |
cbentzel
2012/01/05 18:32:20
Nit: #if !defined(NDEBUG)
is preferred over #ifnd
| |
44 const T& value() const { return iterator_->second; } | |
45 #else | |
46 const T& value() const { return *iterator_; } | |
47 #endif | |
48 | |
49 // Comparing to Pointer from a different PriorityQueue is undefined. | |
50 bool Equals(const Pointer& other) const { | |
51 return (priority_ == other.priority_) && (iterator_ == other.iterator_); | |
52 } | |
53 | |
54 private: | |
55 friend class PriorityQueue; | |
56 // Note that we need iterator not const_iterator to pass to List::erase. | |
57 // When C++0x comes, this could be changed to const_iterator and const could | |
58 // be added to First, Last, and OldestLowest. | |
59 #ifndef NDEBUG | |
60 typedef typename std::list<std::pair<size_t, T> >::iterator ListIterator; | |
cbentzel
2012/01/05 18:32:20
Could be PriorityQueue::List::iterator to prevent
| |
61 #else | |
62 typedef typename std::list<T>::iterator ListIterator; | |
63 #endif | |
64 | |
65 static const size_t kNullPriority = static_cast<size_t>(-1); | |
66 | |
67 Pointer(size_t priority, const ListIterator& iterator) | |
68 : priority_(priority), iterator_(iterator) { | |
69 #ifndef NDEBUG | |
70 id_ = iterator_->first; | |
71 #endif | |
72 } | |
73 | |
74 size_t priority_; | |
75 ListIterator iterator_; | |
76 | |
77 #ifndef NDEBUG | |
78 // Used by the queue to check if a Pointer is valid. | |
79 size_t id_; | |
80 #endif | |
81 }; | |
82 | |
83 // Creates a new queue for |num_priorities|. | |
84 PriorityQueue(size_t num_priorities) | |
cbentzel
2012/01/05 18:32:20
explicit constructor needed.
| |
85 : lists_(num_priorities), size_(0) { | |
86 #ifndef NDEBUG | |
87 next_id_ = 0; | |
88 #endif | |
89 } | |
90 | |
91 // Adds |value| with |priority| to the queue. Returns a pointer to the | |
92 // created element. | |
93 Pointer Insert(const T& value, size_t priority) { | |
94 DCHECK_LT(priority, lists_.size()); | |
95 ++size_; | |
96 List& list = lists_[priority]; | |
97 #ifndef NDEBUG | |
98 size_t id = next_id_; | |
99 valid_ids_.insert(id); | |
100 ++next_id_; | |
101 return Pointer(priority, list.insert(list.end(), | |
cbentzel
2012/01/05 18:32:20
Nit: list.push_back would be clearer than list.ins
szym
2012/01/05 19:00:29
list.push_back returns void.
| |
102 std::make_pair(id, value))); | |
103 #else | |
104 return Pointer(priority, list.insert(list.end(), value)); | |
105 #endif | |
106 } | |
107 | |
108 // Removes the value pointed by |pointer| from the queue. All pointers to this | |
109 // value including |pointer| become invalid. | |
110 void Erase(const Pointer& pointer) { | |
111 DCHECK_LT(pointer.priority_, lists_.size()); | |
112 DCHECK_GT(size_, 0u); | |
113 | |
114 #ifndef NDEBUG | |
115 DCHECK_EQ(1u, valid_ids_.erase(pointer.id_)); | |
116 DCHECK_EQ(pointer.iterator_->first, pointer.id_); | |
117 #endif | |
118 | |
119 --size_; | |
120 lists_[pointer.priority_].erase(pointer.iterator_); | |
121 } | |
122 | |
123 // Returns a pointer to the first value of minimum priority or a null-pointer | |
124 // if empty. | |
125 Pointer FirstMin() { | |
126 if (!size()) return Pointer(); | |
cbentzel
2012/01/05 18:32:20
It would be clearer to just remove this line and t
| |
127 for (size_t i = 0; i < lists_.size(); ++i) | |
cbentzel
2012/01/05 18:32:20
Please use braces in this for loop.
| |
128 if (!lists_[i].empty()) | |
129 return Pointer(i, lists_[i].begin()); | |
130 NOTREACHED(); | |
131 return Pointer(); | |
132 } | |
133 | |
134 // Returns a pointer to the last value of minimum priority or a null-pointer | |
135 // if empty. | |
136 Pointer LastMin() { | |
137 if (!size()) return Pointer(); | |
138 for (size_t i = 0; i < lists_.size(); ++i) | |
139 if (!lists_[i].empty()) | |
140 return Pointer(i, --lists_[i].end()); | |
141 NOTREACHED(); | |
142 return Pointer(); | |
143 } | |
144 | |
145 // Returns a pointer to the first value of maximum priority or a null-pointer | |
146 // if empty. | |
147 Pointer FirstMax() { | |
148 if (!size()) return Pointer(); | |
149 for (size_t i = lists_.size(); i > 0; --i) | |
150 if (!lists_[i - 1].empty()) | |
151 return Pointer(i - 1, lists_[i - 1].begin()); | |
152 NOTREACHED(); | |
153 return Pointer(); | |
154 } | |
155 | |
156 // Returns a pointer to the last value of maximum priority or a null-pointer | |
157 // if empty. | |
158 Pointer LastMax() { | |
159 if (!size()) return Pointer(); | |
160 for (size_t i = lists_.size(); i > 0; --i) | |
cbentzel
2012/01/05 18:32:20
To be pedantic, this should be ListVector::size_ty
| |
161 if (!lists_[i - 1].empty()) | |
cbentzel
2012/01/05 18:32:20
Nit: probably clearer to have a local variable ind
| |
162 return Pointer(i - 1, --lists_[i - 1].end()); | |
163 NOTREACHED(); | |
164 return Pointer(); | |
165 } | |
166 | |
167 // Empties the queue. All pointers become invalid. | |
168 void Clear() { | |
169 for (size_t i = 0; i < lists_.size(); ++i) | |
cbentzel
2012/01/05 18:32:20
BUG: valid_ids_ needs to be cleared here as well.
| |
170 lists_[i].clear(); | |
171 size_ = 0u; | |
172 } | |
173 | |
174 // Returns number of queued values. | |
175 size_t size() const { | |
176 return size_; | |
177 } | |
178 | |
179 private: | |
180 #ifndef NDEBUG | |
181 typedef std::list<std::pair<size_t, T> > List; | |
182 #else | |
183 typedef std::list<T> List; | |
184 #endif | |
185 typedef std::vector<List> ListVector; | |
186 | |
187 #ifndef NDEBUG | |
188 size_t next_id_; | |
189 base::hash_set<size_t> valid_ids_; | |
190 #endif | |
191 | |
192 ListVector lists_; | |
193 size_t size_; | |
cbentzel
2012/01/05 18:32:20
Nit: extra new line.
| |
194 | |
cbentzel
2012/01/05 18:32:20
Should copy-and-assignment be disallowed? I don't
szym
2012/01/05 19:00:29
It can be allowed. But for safety Pointers need to
| |
195 }; | |
196 | |
197 } // namespace net | |
198 | |
199 #endif // NET_BASE_PRIORITY_QUEUE_H_ | |
200 | |
OLD | NEW |