123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- // (C) Copyright Jeremiah Willcock 2004
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_FENCED_PRIORITY_QUEUE_HPP
- #define BOOST_FENCED_PRIORITY_QUEUE_HPP
- #include <vector>
- #include <queue>
- #include <functional>
- #include <boost/pending/queue.hpp>
- // Fenced priority queue
- // Jeremiah Willcock
- // This class implements a fenced priority queue. This is similar to
- // a normal priority queue (sorts its members, and only returns the
- // first), except that members cannot be sorted around a "fence" that
- // can be placed into the buffer. This fence is inserted using the
- // fence() member function or (possibly) implicitly by the top() and
- // pop() methods, and is removed automatically when the elements
- // around it are popped.
- // The implementation is as follows: Q is an unsorted queue that
- // contains the already-sorted list data, and PQ is a priority queue
- // that contains new elements (since the last fence) that have yet to
- // be sorted. New elements are inserted into PQ, and a fence moves
- // all elements in PQ into the back of Q in sorted order. Elements
- // are then popped from the front of Q, and if that is empty the front
- // of PQ.
- namespace boost
- {
- template < class T, class Compare = std::less< T >, bool implicit_fence = true,
- class Buffer = boost::queue< T > >
- class fenced_priority_queue
- {
- public:
- typedef T value_type;
- typedef typename Buffer::size_type size_type;
- fenced_priority_queue(const Compare _comp = Compare()) : PQ(_comp) {}
- void push(const T& data);
- void pop(void);
- T& top(void);
- const T& top(void) const;
- size_type size(void) const;
- bool empty(void) const;
- void fence(void);
- private:
- void fence(void) const;
- // let them mutable to allow const version of top and the same
- // semantics with non-constant version. Rich Lee
- mutable std::priority_queue< T, std::vector< T >, Compare > PQ;
- mutable Buffer Q;
- };
- template < class T, class Compare, bool implicit_fence, class Buffer >
- inline void fenced_priority_queue< T, Compare, implicit_fence, Buffer >::push(
- const T& t)
- {
- // Push a new element after the last fence. This puts it into the
- // priority queue to be sorted with all other elements in its
- // partition.
- PQ.push(t);
- }
- template < class T, class Compare, bool implicit_fence, class Buffer >
- inline void fenced_priority_queue< T, Compare, implicit_fence, Buffer >::pop(
- void)
- {
- // Pop one element from the front of the queue. Removes from the
- // already-sorted part of the queue if it is non-empty, otherwise
- // removes from the new-element priority queue. Runs an implicit
- // "fence" operation if the implicit_fence template argument is
- // true.
- if (implicit_fence)
- fence();
- if (!Q.empty())
- Q.pop();
- else
- PQ.pop();
- }
- template < class T, class Compare, bool implicit_fence, class Buffer >
- inline T& fenced_priority_queue< T, Compare, implicit_fence, Buffer >::top(void)
- {
- // Get the top element from the queue. This element comes from Q if
- // possible, otherwise from PQ. Causes an implicit "fence"
- // operation if the implicit_fence template argument is true.
- if (implicit_fence)
- fence();
- if (!Q.empty())
- return Q.top();
- else
- // std::priority_queue only have const version of top. Rich Lee
- return const_cast< T& >(PQ.top());
- }
- template < class T, class Compare, bool implicit_fence, class Buffer >
- inline const T&
- fenced_priority_queue< T, Compare, implicit_fence, Buffer >::top(void) const
- {
- if (implicit_fence)
- fence();
- if (!Q.empty())
- return Q.top();
- else
- return PQ.top();
- }
- template < class T, class Compare, bool implicit_fence, class Buffer >
- inline typename fenced_priority_queue< T, Compare, implicit_fence,
- Buffer >::size_type
- fenced_priority_queue< T, Compare, implicit_fence, Buffer >::size(void) const
- {
- // Returns the size of the queue (both parts together).
- return Q.size() + PQ.size();
- }
- template < class T, class Compare, bool implicit_fence, class Buffer >
- inline bool fenced_priority_queue< T, Compare, implicit_fence, Buffer >::empty(
- void) const
- {
- // Returns if the queue is empty, i.e. both parts are empty.
- return Q.empty() && PQ.empty();
- }
- template < class T, class Compare, bool implicit_fence, class Buffer >
- inline void fenced_priority_queue< T, Compare, implicit_fence, Buffer >::fence(
- void)
- {
- // Perform a fence operation. Remove elements from PQ in sorted
- // order and insert them in the back of Q.
- while (!PQ.empty())
- {
- Q.push(PQ.top());
- PQ.pop();
- }
- }
- template < class T, class Compare, bool implicit_fence, class Buffer >
- inline void fenced_priority_queue< T, Compare, implicit_fence, Buffer >::fence(
- void) const
- {
- // Perform a fence operation. Remove elements from PQ in sorted
- // order and insert them in the back of Q.
- while (!PQ.empty())
- {
- Q.push(PQ.top());
- PQ.pop();
- }
- }
- }
- #endif /* BOOST_FENCED_PRIORITY_QUEUE_HPP */
|