4b6effe849
[SVN r25809]
153 lines
5.1 KiB
C++
153 lines
5.1 KiB
C++
// (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 */
|