diff options
Diffstat (limited to 'chromium/net/base/priority_queue.h')
-rw-r--r-- | chromium/net/base/priority_queue.h | 238 |
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_ |