fenced_priority_queue.hpp 5.1 KB

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