My Project
 All Classes Files Functions Variables Enumerations Enumerator Friends Macros Pages
CircBuf.h
Go to the documentation of this file.
1 // $Id: CircBuf.h,v 1.1.1.1 2009/07/06 23:57:25 eml Exp $
2 
3 #ifndef GCP_UTIL_CIRCBUF_H
4 #define GCP_UTIL_CIRCBUF_H
5 
16 #include <iostream>
17 #include <valarray>
18 
19 #include "gcp/util/common/Exception.h"
20 
21 namespace gcp {
22  namespace util {
23 
24  // Forward declarations needed before we can declare the output operators below
25 
26  template <class type>
27  class CircBuf;
28 
29  template <class type>
30  class Node;
31 
32  // Output Operators for classes defined in this file
33 
34  template<class type>
35  std::ostream& operator<<(std::ostream& os, const CircBuf<type>& obj);
36 
37  template<class type>
38  std::ostream& operator<<(std::ostream& os, const Node<type>& obj);
39 
40  //=======================================================================
41  // A utility class to encapsulate a single node in the circular buffer
42  //=======================================================================
43 
44  template<class type>
45  class Node {
46  public:
47 
48  unsigned id_;
49  type node_;
50 
51  Node* next_;
52  Node* prev_;
53 
54  Node() {
55  id_ = 0;
56  node_ = 0;
57  next_ = 0;
58  prev_ = 0;
59  }
60 
61  virtual ~Node() {};
62  };
63 
64  //=======================================================================
65  // Circular buffer class methods.
66  //
67  // This class is intended to be used as storage for a sequential
68  // stream of objects where at any given point in time we are
69  // interested in an n-element stretch of them.
70  //
71  // An example is storage for on-the-fly computation of an n-point
72  // FFT of timestream data. As new samples are clocked in, the
73  // oldest ones are simply overwritten, so that a call to copy
74  // returns an array n-elements long containing the latest data.
75  //
76  //=======================================================================
77 
78  template <class type>
79  class CircBuf {
80  public:
81 
82  // Constructor.
83 
84  CircBuf(unsigned n=1);
85 
86  // Copy Constructor.
87 
88  CircBuf(const CircBuf<type>& objToBeCopied);
89 
90  // Copy Constructor.
91 
92  CircBuf(CircBuf<type>& objToBeCopied);
93 
94  // Const Assignment Operator.
95 
96  void operator=(const CircBuf<type>& objToBeAssigned);
97 
98  // Assignment Operator.
99 
100  void operator=(CircBuf<type>& objToBeAssigned);
101 
102  // Destructor.
103 
104  virtual ~CircBuf();
105 
106  // Push a new object onto the head of the queue. If the buffer
107  // is full, this will displace the oldest one.
108 
109  void push(type);
110 
111  // Return the newest/oldest element in the buffer
112 
113  type newest();
114  type oldest();
115 
116  // Return the length of the buffer
117 
118  unsigned size();
119 
120  // Return the number of objects currently in the buffer (could
121  // be < size())
122 
123  unsigned nInBuffer();
124 
125  // resize the buffer
126 
127  void resize(unsigned n);
128 
129  // (re-) initialize the buffer
130 
131  void initialize(unsigned n);
132 
133  // Unsafe method to copy the current queue to an array
134 
135  void copy(type* ptr);
136 
137  // Safe method to copy the current queue to an array
138 
139  std::valarray<type> copy();
140 
141  private:
142 
143  unsigned nTotal_;
144  unsigned nInBuf_;
145 
146  Node<type>* head_;
147  Node<type>* tail_;
148 
149  std::valarray<Node<type> > nodes_;
150 
151  }; // End template class CircBuf
152 
153  //-----------------------------------------------------------------------
154  // Implementation
155  //-----------------------------------------------------------------------
156 
157  // Constructors
158 
159  template <class type>
160  CircBuf<type>::CircBuf(unsigned n)
161  {
162  initialize(n);
163  }
164 
165  // Copy Constructor.
166 
167  template <class type>
168  CircBuf<type>::CircBuf(const CircBuf<type>& objToBeCopied)
169  {
170  *this = (CircBuf<type>&)objToBeCopied;
171  }
172 
173  // Copy Constructor.
174 
175  template <class type>
176  CircBuf<type>::CircBuf(CircBuf<type>& objToBeCopied)
177  {
178  *this = objToBeCopied;
179  };
180 
181 
182  // Const Assignment Operator.
183 
184  template <class type>
185  void CircBuf<type>::operator=(const CircBuf<type>& objToBeAssigned)
186  {
187  *this = (CircBuf<type>&)objToBeAssigned;
188  };
189 
190  // Assignment Operator.
191 
192  template <class type>
193  void CircBuf<type>::operator=(CircBuf<type>& objToBeAssigned)
194  {
195  std::cout << "Calling default assignment operator for class: CircBuf" << std::endl;
196  };
197 
198  // Output Operator.
199 
200  template <class type>
201  std::ostream& operator<<(std::ostream& os, CircBuf<type>& obj)
202  {
203  COUT("Default output operator called");
204  }
205 
206  // Destructor.
207 
208  template <class type>
209  CircBuf<type>::~CircBuf() {};
210 
211  // Push a new object onto the head of the queue. If the queue is
212  // full, this will displace the oldest one.
213 
214  template <class type>
215  void CircBuf<type>::push(type obj)
216  {
217  tail_->node_ = obj;
218  tail_ = tail_->next_;
219 
220  if(tail_ == head_) {
221  head_ = head_->next_;
222  } else {
223  nInBuf_++;
224  }
225  }
226 
227  // Return the oldest (head) sample
228 
229  template <class type>
230  type CircBuf<type>::oldest()
231  {
232  return head_->node_;
233  }
234 
235  template <class type>
236  type CircBuf<type>::newest()
237  {
238  return tail_->prev_->node_;
239  }
240 
241  // Return the length of the buffer
242 
243  template<class type>
244  unsigned CircBuf<type>::size()
245  {
246  return nTotal_;
247  }
248 
249  // Return the number of objects currently in the buffer (could
250  // be < size())
251 
252  template<class type>
253  unsigned CircBuf<type>::nInBuffer()
254  {
255  return nInBuf_;
256  }
257 
258  // resize the buffer
259 
260  template<class type>
261  void CircBuf<type>::resize(unsigned n)
262  {
263  initialize(n);
264  }
265 
266  template<class type>
267  void CircBuf<type>::initialize(unsigned n)
268  {
269  nInBuf_ = 0;
270 
271  // Make the queue larger than the number of nodes needed by
272  // one. This is so that tests like for(iter = head; iter !=
273  // tail; iter++) will do the correct thing (otherwise, this
274  // loop would stop one short)
275 
276  if(nodes_.size() != n+1)
277  nodes_.resize(n+1);
278 
279  nTotal_ = n;
280 
281  // And re-link the list
282 
283  for(unsigned iNode=0; iNode <= n; iNode++) {
284  nodes_[iNode].id_ = iNode;
285  nodes_[iNode].node_ = 0;
286  nodes_[iNode].prev_ = &nodes_[iNode==0 ? n : iNode-1];
287  nodes_[iNode].next_ = &nodes_[iNode==n ? 0 : iNode+1];
288  }
289 
290  // And set the queue ptr pointing to the head of the list
291 
292  head_ = &nodes_[0];
293 
294  // And set the queue ptr pointing to the tail of the list. This
295  // should always point to the next unused slot in the array.
296  // Since our arry is 1 element longer than we need for
297  // computation, this will start pointing to the 0th element, and
298  // eventually will always point to element nMaxNodes-1
299 
300  tail_ = &nodes_[0];
301  }
302 
303  // Unsafe method to copy the current queue to an array
304 
305  template<class type>
306  void CircBuf<type>::copy(type* ptr)
307  {
308  unsigned i=0;
309 
310  for(Node<type>* iter = head_; iter != tail_; iter = iter->next_, i++)
311  *(ptr+i) = iter->node_;
312  }
313 
314  // Safe method to copy the current queue to an array
315 
316  template<class type>
317  std::valarray<type> CircBuf<type>::copy()
318  {
319  std::valarray<type> arr(nInBuf_);
320  copy(&arr[0]);
321  return arr;
322  }
323 
324  // Print out a buffer
325 
326  template <class type>
327  std::ostream& operator<<(std::ostream& os,
328  const CircBuf<type>& buf)
329  {
330  COUT("Calling default output operator for CircBuf");
331  }
332 
333  // Print out a buffer
334 
335  template <class type>
336  std::ostream& operator<<(std::ostream& os,
337  const Node<type>& node)
338  {
339  COUT(node.node_ << " " << node.id_);
340  }
341 
342 
343  } // End namespace util
344 } // End namespace gcp
345 
346 
347 
348 #endif // End #ifndef GCP_UTIL_CIRCBUF_H
Definition: CircBuf.h:30
Definition: eval_defs.h:51
Definition: CircBuf.h:27