summaryrefslogtreecommitdiff
path: root/boost/pending/fenced_priority_queue.hpp
blob: 4d4e3aff942fa7401b003d0414fd787e1cfc2318 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//  (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 */