summaryrefslogtreecommitdiff
path: root/chromium/net/base/priority_queue.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/base/priority_queue.h')
-rw-r--r--chromium/net/base/priority_queue.h238
1 files changed, 238 insertions, 0 deletions
diff --git a/chromium/net/base/priority_queue.h b/chromium/net/base/priority_queue.h
new file mode 100644
index 00000000000..b758ca45dea
--- /dev/null
+++ b/chromium/net/base/priority_queue.h
@@ -0,0 +1,238 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_BASE_PRIORITY_QUEUE_H_
+#define NET_BASE_PRIORITY_QUEUE_H_
+
+#include <list>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/threading/non_thread_safe.h"
+#include "net/base/net_export.h"
+
+#if !defined(NDEBUG)
+#include "base/containers/hash_tables.h"
+#endif
+
+namespace net {
+
+// A simple priority queue. The order of values is by priority and then FIFO.
+// Unlike the std::priority_queue, this implementation allows erasing elements
+// from the queue, and all operations are O(p) time for p priority levels.
+// The queue is agnostic to priority ordering (whether 0 precedes 1).
+// If the highest priority is 0, FirstMin() returns the first in order.
+//
+// In debug-mode, the internal queues store (id, value) pairs where id is used
+// to validate Pointers.
+//
+template<typename T>
+class PriorityQueue : public base::NonThreadSafe {
+ private:
+ // This section is up-front for Pointer only.
+#if !defined(NDEBUG)
+ typedef std::list<std::pair<unsigned, T> > List;
+#else
+ typedef std::list<T> List;
+#endif
+
+ public:
+ typedef uint32 Priority;
+
+ // A pointer to a value stored in the queue. The pointer becomes invalid
+ // when the queue is destroyed or cleared, or the value is erased.
+ class Pointer {
+ public:
+ // Constructs a null pointer.
+ Pointer() : priority_(kNullPriority) {
+#if !defined(NDEBUG)
+ id_ = static_cast<unsigned>(-1);
+#endif
+ }
+
+ Pointer(const Pointer& p) : priority_(p.priority_), iterator_(p.iterator_) {
+#if !defined(NDEBUG)
+ id_ = p.id_;
+#endif
+ }
+
+ Pointer& operator=(const Pointer& p) {
+ // Self-assignment is benign.
+ priority_ = p.priority_;
+ iterator_ = p.iterator_;
+#if !defined(NDEBUG)
+ id_ = p.id_;
+#endif
+ return *this;
+ }
+
+ bool is_null() const { return priority_ == kNullPriority; }
+
+ Priority priority() const { return priority_; }
+
+#if !defined(NDEBUG)
+ const T& value() const { return iterator_->second; }
+#else
+ const T& value() const { return *iterator_; }
+#endif
+
+ // Comparing to Pointer from a different PriorityQueue is undefined.
+ bool Equals(const Pointer& other) const {
+ return (priority_ == other.priority_) && (iterator_ == other.iterator_);
+ }
+
+ void Reset() {
+ *this = Pointer();
+ }
+
+ private:
+ friend class PriorityQueue;
+
+ // Note that we need iterator not const_iterator to pass to List::erase.
+ // When C++0x comes, this could be changed to const_iterator and const could
+ // be added to First, Last, and OldestLowest.
+ typedef typename PriorityQueue::List::iterator ListIterator;
+
+ static const Priority kNullPriority = static_cast<Priority>(-1);
+
+ Pointer(Priority priority, const ListIterator& iterator)
+ : priority_(priority), iterator_(iterator) {
+#if !defined(NDEBUG)
+ id_ = iterator_->first;
+#endif
+ }
+
+ Priority priority_;
+ ListIterator iterator_;
+
+#if !defined(NDEBUG)
+ // Used by the queue to check if a Pointer is valid.
+ unsigned id_;
+#endif
+ };
+
+ // Creates a new queue for |num_priorities|.
+ explicit PriorityQueue(Priority num_priorities)
+ : lists_(num_priorities), size_(0) {
+#if !defined(NDEBUG)
+ next_id_ = 0;
+#endif
+ }
+
+ // Adds |value| with |priority| to the queue. Returns a pointer to the
+ // created element.
+ Pointer Insert(const T& value, Priority priority) {
+ DCHECK(CalledOnValidThread());
+ DCHECK_LT(priority, lists_.size());
+ ++size_;
+ List& list = lists_[priority];
+#if !defined(NDEBUG)
+ unsigned id = next_id_;
+ valid_ids_.insert(id);
+ ++next_id_;
+ return Pointer(priority, list.insert(list.end(),
+ std::make_pair(id, value)));
+#else
+ return Pointer(priority, list.insert(list.end(), value));
+#endif
+ }
+
+ // Removes the value pointed by |pointer| from the queue. All pointers to this
+ // value including |pointer| become invalid.
+ void Erase(const Pointer& pointer) {
+ DCHECK(CalledOnValidThread());
+ DCHECK_LT(pointer.priority_, lists_.size());
+ DCHECK_GT(size_, 0u);
+
+#if !defined(NDEBUG)
+ DCHECK_EQ(1u, valid_ids_.erase(pointer.id_));
+ DCHECK_EQ(pointer.iterator_->first, pointer.id_);
+#endif
+
+ --size_;
+ lists_[pointer.priority_].erase(pointer.iterator_);
+ }
+
+ // Returns a pointer to the first value of minimum priority or a null-pointer
+ // if empty.
+ Pointer FirstMin() {
+ DCHECK(CalledOnValidThread());
+ for (size_t i = 0; i < lists_.size(); ++i) {
+ if (!lists_[i].empty())
+ return Pointer(i, lists_[i].begin());
+ }
+ return Pointer();
+ }
+
+ // Returns a pointer to the last value of minimum priority or a null-pointer
+ // if empty.
+ Pointer LastMin() {
+ DCHECK(CalledOnValidThread());
+ for (size_t i = 0; i < lists_.size(); ++i) {
+ if (!lists_[i].empty())
+ return Pointer(i, --lists_[i].end());
+ }
+ return Pointer();
+ }
+
+ // Returns a pointer to the first value of maximum priority or a null-pointer
+ // if empty.
+ Pointer FirstMax() {
+ DCHECK(CalledOnValidThread());
+ for (size_t i = lists_.size(); i > 0; --i) {
+ size_t index = i - 1;
+ if (!lists_[index].empty())
+ return Pointer(index, lists_[index].begin());
+ }
+ return Pointer();
+ }
+
+ // Returns a pointer to the last value of maximum priority or a null-pointer
+ // if empty.
+ Pointer LastMax() {
+ DCHECK(CalledOnValidThread());
+ for (size_t i = lists_.size(); i > 0; --i) {
+ size_t index = i - 1;
+ if (!lists_[index].empty())
+ return Pointer(index, --lists_[index].end());
+ }
+ return Pointer();
+ }
+
+ // Empties the queue. All pointers become invalid.
+ void Clear() {
+ DCHECK(CalledOnValidThread());
+ for (size_t i = 0; i < lists_.size(); ++i) {
+ lists_[i].clear();
+ }
+#if !defined(NDEBUG)
+ valid_ids_.clear();
+#endif
+ size_ = 0u;
+ }
+
+ // Returns number of queued values.
+ size_t size() const {
+ DCHECK(CalledOnValidThread());
+ return size_;
+ }
+
+ private:
+ typedef std::vector<List> ListVector;
+
+#if !defined(NDEBUG)
+ unsigned next_id_;
+ base::hash_set<unsigned> valid_ids_;
+#endif
+
+ ListVector lists_;
+ size_t size_;
+
+ DISALLOW_COPY_AND_ASSIGN(PriorityQueue);
+};
+
+} // namespace net
+
+#endif // NET_BASE_PRIORITY_QUEUE_H_