fenced_priority_queue.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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. {
  29. template < class T, class Compare = std::less< T >, bool implicit_fence = true,
  30. class Buffer = boost::queue< T > >
  31. class fenced_priority_queue
  32. {
  33. public:
  34. typedef T value_type;
  35. typedef typename Buffer::size_type size_type;
  36. fenced_priority_queue(const Compare _comp = Compare()) : PQ(_comp) {}
  37. void push(const T& data);
  38. void pop(void);
  39. T& top(void);
  40. const T& top(void) const;
  41. size_type size(void) const;
  42. bool empty(void) const;
  43. void fence(void);
  44. private:
  45. void fence(void) const;
  46. // let them mutable to allow const version of top and the same
  47. // semantics with non-constant version. Rich Lee
  48. mutable std::priority_queue< T, std::vector< T >, Compare > PQ;
  49. mutable Buffer Q;
  50. };
  51. template < class T, class Compare, bool implicit_fence, class Buffer >
  52. inline void fenced_priority_queue< T, Compare, implicit_fence, Buffer >::push(
  53. const T& t)
  54. {
  55. // Push a new element after the last fence. This puts it into the
  56. // priority queue to be sorted with all other elements in its
  57. // partition.
  58. PQ.push(t);
  59. }
  60. template < class T, class Compare, bool implicit_fence, class Buffer >
  61. inline void fenced_priority_queue< T, Compare, implicit_fence, Buffer >::pop(
  62. void)
  63. {
  64. // Pop one element from the front of the queue. Removes from the
  65. // already-sorted part of the queue if it is non-empty, otherwise
  66. // removes from the new-element priority queue. Runs an implicit
  67. // "fence" operation if the implicit_fence template argument is
  68. // true.
  69. if (implicit_fence)
  70. fence();
  71. if (!Q.empty())
  72. Q.pop();
  73. else
  74. PQ.pop();
  75. }
  76. template < class T, class Compare, bool implicit_fence, class Buffer >
  77. inline T& fenced_priority_queue< T, Compare, implicit_fence, Buffer >::top(void)
  78. {
  79. // Get the top element from the queue. This element comes from Q if
  80. // possible, otherwise from PQ. Causes an implicit "fence"
  81. // operation if the implicit_fence template argument is true.
  82. if (implicit_fence)
  83. fence();
  84. if (!Q.empty())
  85. return Q.top();
  86. else
  87. // std::priority_queue only have const version of top. Rich Lee
  88. return const_cast< T& >(PQ.top());
  89. }
  90. template < class T, class Compare, bool implicit_fence, class Buffer >
  91. inline const T&
  92. fenced_priority_queue< T, Compare, implicit_fence, Buffer >::top(void) const
  93. {
  94. if (implicit_fence)
  95. fence();
  96. if (!Q.empty())
  97. return Q.top();
  98. else
  99. return PQ.top();
  100. }
  101. template < class T, class Compare, bool implicit_fence, class Buffer >
  102. inline typename fenced_priority_queue< T, Compare, implicit_fence,
  103. Buffer >::size_type
  104. fenced_priority_queue< T, Compare, implicit_fence, Buffer >::size(void) const
  105. {
  106. // Returns the size of the queue (both parts together).
  107. return Q.size() + PQ.size();
  108. }
  109. template < class T, class Compare, bool implicit_fence, class Buffer >
  110. inline bool fenced_priority_queue< T, Compare, implicit_fence, Buffer >::empty(
  111. void) const
  112. {
  113. // Returns if the queue is empty, i.e. both parts are empty.
  114. return Q.empty() && PQ.empty();
  115. }
  116. template < class T, class Compare, bool implicit_fence, class Buffer >
  117. inline void fenced_priority_queue< T, Compare, implicit_fence, Buffer >::fence(
  118. void)
  119. {
  120. // Perform a fence operation. Remove elements from PQ in sorted
  121. // order and insert them in the back of Q.
  122. while (!PQ.empty())
  123. {
  124. Q.push(PQ.top());
  125. PQ.pop();
  126. }
  127. }
  128. template < class T, class Compare, bool implicit_fence, class Buffer >
  129. inline void fenced_priority_queue< T, Compare, implicit_fence, Buffer >::fence(
  130. void) const
  131. {
  132. // Perform a fence operation. Remove elements from PQ in sorted
  133. // order and insert them in the back of Q.
  134. while (!PQ.empty())
  135. {
  136. Q.push(PQ.top());
  137. PQ.pop();
  138. }
  139. }
  140. }
  141. #endif /* BOOST_FENCED_PRIORITY_QUEUE_HPP */