// (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 #include #include #include // 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, bool implicit_fence = true, class Buffer = boost::queue > 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, Compare> PQ; mutable Buffer Q; }; template inline void fenced_priority_queue:: 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 inline void fenced_priority_queue:: 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 inline T& fenced_priority_queue:: 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(PQ.top()); } template inline const T& fenced_priority_queue:: top(void) const { if (implicit_fence) fence(); if ( !Q.empty() ) return Q.top(); else return PQ.top(); } template inline typename fenced_priority_queue::size_type fenced_priority_queue:: size(void) const { // Returns the size of the queue (both parts together). return Q.size() + PQ.size(); } template inline bool fenced_priority_queue:: empty(void) const { // Returns if the queue is empty, i.e. both parts are empty. return Q.empty() && PQ.empty(); } template inline void fenced_priority_queue:: 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 inline void fenced_priority_queue:: 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 */