Chris@16
|
1 // (C) Copyright Jeremiah Willcock 2004
|
Chris@16
|
2 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
3 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
4 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 #ifndef BOOST_FENCED_PRIORITY_QUEUE_HPP
|
Chris@16
|
7 #define BOOST_FENCED_PRIORITY_QUEUE_HPP
|
Chris@16
|
8
|
Chris@16
|
9 #include <vector>
|
Chris@16
|
10 #include <queue>
|
Chris@16
|
11 #include <functional>
|
Chris@16
|
12 #include <boost/pending/queue.hpp>
|
Chris@16
|
13
|
Chris@16
|
14 // Fenced priority queue
|
Chris@16
|
15 // Jeremiah Willcock
|
Chris@16
|
16
|
Chris@16
|
17 // This class implements a fenced priority queue. This is similar to
|
Chris@16
|
18 // a normal priority queue (sorts its members, and only returns the
|
Chris@16
|
19 // first), except that members cannot be sorted around a "fence" that
|
Chris@16
|
20 // can be placed into the buffer. This fence is inserted using the
|
Chris@16
|
21 // fence() member function or (possibly) implicitly by the top() and
|
Chris@16
|
22 // pop() methods, and is removed automatically when the elements
|
Chris@16
|
23 // around it are popped.
|
Chris@16
|
24
|
Chris@16
|
25 // The implementation is as follows: Q is an unsorted queue that
|
Chris@16
|
26 // contains the already-sorted list data, and PQ is a priority queue
|
Chris@16
|
27 // that contains new elements (since the last fence) that have yet to
|
Chris@16
|
28 // be sorted. New elements are inserted into PQ, and a fence moves
|
Chris@16
|
29 // all elements in PQ into the back of Q in sorted order. Elements
|
Chris@16
|
30 // are then popped from the front of Q, and if that is empty the front
|
Chris@16
|
31 // of PQ.
|
Chris@16
|
32
|
Chris@16
|
33 namespace boost {
|
Chris@16
|
34
|
Chris@16
|
35 template<class T, class Compare = std::less<T>, bool implicit_fence = true,
|
Chris@16
|
36 class Buffer = boost::queue<T> >
|
Chris@16
|
37 class fenced_priority_queue {
|
Chris@16
|
38 public:
|
Chris@16
|
39 typedef T value_type;
|
Chris@16
|
40 typedef typename Buffer::size_type size_type;
|
Chris@16
|
41
|
Chris@16
|
42 fenced_priority_queue(const Compare _comp = Compare() )
|
Chris@16
|
43 : PQ(_comp) {}
|
Chris@16
|
44
|
Chris@16
|
45 void push(const T& data);
|
Chris@16
|
46 void pop(void);
|
Chris@16
|
47 T& top(void);
|
Chris@16
|
48 const T& top(void) const;
|
Chris@16
|
49 size_type size(void) const;
|
Chris@16
|
50 bool empty(void) const;
|
Chris@16
|
51 void fence(void);
|
Chris@16
|
52
|
Chris@16
|
53 private:
|
Chris@16
|
54 void fence(void) const;
|
Chris@16
|
55
|
Chris@16
|
56 //let them mutable to allow const version of top and the same
|
Chris@16
|
57 //semantics with non-constant version. Rich Lee
|
Chris@16
|
58 mutable std::priority_queue<T, std::vector<T>, Compare> PQ;
|
Chris@16
|
59 mutable Buffer Q;
|
Chris@16
|
60 };
|
Chris@16
|
61
|
Chris@16
|
62 template<class T, class Compare, bool implicit_fence, class Buffer>
|
Chris@16
|
63 inline void
|
Chris@16
|
64 fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
|
Chris@16
|
65 push(const T &t) {
|
Chris@16
|
66 // Push a new element after the last fence. This puts it into the
|
Chris@16
|
67 // priority queue to be sorted with all other elements in its
|
Chris@16
|
68 // partition.
|
Chris@16
|
69 PQ.push(t);
|
Chris@16
|
70 }
|
Chris@16
|
71
|
Chris@16
|
72 template<class T, class Compare, bool implicit_fence, class Buffer>
|
Chris@16
|
73 inline void fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
|
Chris@16
|
74 pop(void) {
|
Chris@16
|
75 // Pop one element from the front of the queue. Removes from the
|
Chris@16
|
76 // already-sorted part of the queue if it is non-empty, otherwise
|
Chris@16
|
77 // removes from the new-element priority queue. Runs an implicit
|
Chris@16
|
78 // "fence" operation if the implicit_fence template argument is
|
Chris@16
|
79 // true.
|
Chris@16
|
80 if (implicit_fence) fence();
|
Chris@16
|
81 if ( !Q.empty() )
|
Chris@16
|
82 Q.pop();
|
Chris@16
|
83 else
|
Chris@16
|
84 PQ.pop();
|
Chris@16
|
85 }
|
Chris@16
|
86
|
Chris@16
|
87 template<class T, class Compare, bool implicit_fence, class Buffer>
|
Chris@16
|
88 inline T& fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
|
Chris@16
|
89 top(void) {
|
Chris@16
|
90 // Get the top element from the queue. This element comes from Q if
|
Chris@16
|
91 // possible, otherwise from PQ. Causes an implicit "fence"
|
Chris@16
|
92 // operation if the implicit_fence template argument is true.
|
Chris@16
|
93 if (implicit_fence) fence();
|
Chris@16
|
94 if ( !Q.empty() )
|
Chris@16
|
95 return Q.top();
|
Chris@16
|
96 else
|
Chris@16
|
97 //std::priority_queue only have const version of top. Rich Lee
|
Chris@16
|
98 return const_cast<T&>(PQ.top());
|
Chris@16
|
99 }
|
Chris@16
|
100
|
Chris@16
|
101 template<class T, class Compare, bool implicit_fence, class Buffer>
|
Chris@16
|
102 inline const T&
|
Chris@16
|
103 fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
|
Chris@16
|
104 top(void) const {
|
Chris@16
|
105 if (implicit_fence) fence();
|
Chris@16
|
106 if ( !Q.empty() )
|
Chris@16
|
107 return Q.top();
|
Chris@16
|
108 else
|
Chris@16
|
109 return PQ.top();
|
Chris@16
|
110 }
|
Chris@16
|
111
|
Chris@16
|
112 template<class T, class Compare, bool implicit_fence, class Buffer>
|
Chris@16
|
113 inline typename fenced_priority_queue<T, Compare, implicit_fence, Buffer>::size_type
|
Chris@16
|
114 fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
|
Chris@16
|
115 size(void) const {
|
Chris@16
|
116 // Returns the size of the queue (both parts together).
|
Chris@16
|
117 return Q.size() + PQ.size();
|
Chris@16
|
118 }
|
Chris@16
|
119
|
Chris@16
|
120 template<class T, class Compare, bool implicit_fence, class Buffer>
|
Chris@16
|
121 inline bool
|
Chris@16
|
122 fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
|
Chris@16
|
123 empty(void) const {
|
Chris@16
|
124 // Returns if the queue is empty, i.e. both parts are empty.
|
Chris@16
|
125 return Q.empty() && PQ.empty();
|
Chris@16
|
126 }
|
Chris@16
|
127
|
Chris@16
|
128 template<class T, class Compare, bool implicit_fence, class Buffer>
|
Chris@16
|
129 inline void
|
Chris@16
|
130 fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
|
Chris@16
|
131 fence(void) {
|
Chris@16
|
132 // Perform a fence operation. Remove elements from PQ in sorted
|
Chris@16
|
133 // order and insert them in the back of Q.
|
Chris@16
|
134 while ( !PQ.empty() ) {
|
Chris@16
|
135 Q.push(PQ.top());
|
Chris@16
|
136 PQ.pop();
|
Chris@16
|
137 }
|
Chris@16
|
138 }
|
Chris@16
|
139 template<class T, class Compare, bool implicit_fence, class Buffer>
|
Chris@16
|
140 inline void
|
Chris@16
|
141 fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
|
Chris@16
|
142 fence(void) const {
|
Chris@16
|
143 // Perform a fence operation. Remove elements from PQ in sorted
|
Chris@16
|
144 // order and insert them in the back of Q.
|
Chris@16
|
145 while ( !PQ.empty() ) {
|
Chris@16
|
146 Q.push(PQ.top());
|
Chris@16
|
147 PQ.pop();
|
Chris@16
|
148 }
|
Chris@16
|
149 }
|
Chris@16
|
150
|
Chris@16
|
151 }
|
Chris@16
|
152 #endif /* BOOST_FENCED_PRIORITY_QUEUE_HPP */
|