RingBuffer.h
1 /* -*- C++ -*-.***************************************************************************************************
2  Author: Ben Strutt
3  Email: b.strutt.12@ucl.ac.uk
4 
5  Description:
6  A simple ring buffer class.
7 *************************************************************************************************************** */
8 
9 #ifndef RINGBUFFER_H
10 #define RINGBUFFER_H
11 
12 #include <queue>
13 #include <iostream>
14 
15 // ROOT data types
16 #include <Rtypes.h>
17 
18 
19 class RingBuffer{
20 
21 public:
22 
23  enum {
24  default_size = 100
25  };
26 
27  // I have no idea what the proper stl iterators look like on the inside,
28  // so this is probably not how you're supposed to do this
29  class iterator{
30  public:
31  iterator(RingBuffer* rb=NULL, UInt_t vi=0) : ringBuffer(rb), vecIndex(vi){}
32  virtual ~iterator(){}
33 
34  iterator& operator=(const iterator& rhs){
35  this->ringBuffer = rhs.ringBuffer;
36  this->vecIndex = rhs.vecIndex;
37  return (*this);
38  }
39 
40  iterator& operator++(){
41  vecIndex = vecIndex < (int)ringBuffer->fSize ? vecIndex + 1 : 0;
42  return (*this);
43  }
44 
45  iterator operator++(int){
46  iterator tmp(*this);
47  operator++();
48  return tmp;
49  }
50 
51  iterator& operator--(){
52  vecIndex = vecIndex == 0 ? ringBuffer->fSize: vecIndex - 1;
53  return (*this);
54  }
55 
56  iterator operator--(int){
57  iterator tmp(*this);
58  operator--();
59  return tmp;
60  }
61 
62  // the underlying order probably isn't what people expect, so I'm gonna leave commented out for now.
63 
64  // iterator& operator+=(int i){
65  // vecIndex = (vecIndex + i) % ringBuffer->fSize;
66  // return (*this);
67  // }
68 
69  // iterator& operator-=(int i){
70  // operator+=(i);
71  // vecIndex = vecIndex < 0 ? vecIndex + ringBuffer->fSize : vecIndex;
72  // return (*this);
73  // }
74 
75  // iterator operator+(int i){
76  // iterator tmp(*this);
77  // tmp+=i;
78  // return tmp;
79  // }
80 
81  // iterator operator-(int i){
82  // iterator tmp(*this);
83  // tmp-=i;
84  // return tmp;
85  // }
86 
87  double& operator*(){
88  return ringBuffer->elements[vecIndex];
89  }
90 
91  double* operator->(){
92  return &(operator*());
93  }
94 
95  bool operator==(const iterator& rhs) const{
96  return (vecIndex == rhs.vecIndex && ringBuffer == rhs.ringBuffer);
97  }
98 
99  bool operator!=(const iterator& rhs) const{
100  return !(operator==(rhs));
101  }
102 
103  private:
104  RingBuffer* ringBuffer;
105  mutable Int_t vecIndex;
106  };
107 
108 
109  friend class iterator;
110 
111 
112  explicit RingBuffer(UInt_t numElementsInput);
113 
114  Double_t insert(Double_t value); /* Put an element in, returns the value of a removed element */
115  Double_t getSum() const{return sum;}
116  Double_t getMean() const{return numRingElements > 0 ? sum/numRingElements : 0;}
117 
118 
119  iterator begin(){ // should point to the oldest element
120  return iterator(this, oldestElement());
121  }
122  iterator end(){
123  return iterator(this, nextElement);
124  }
125 
126  size_t size() const{return fSize;} // logical size of the container
127  size_t numElements() const {return numRingElements;} // the number of elements in the buffer
128 
129 private:
130 
131  Double_t sum;
132  UInt_t fSize;
133  UInt_t numRingElements; // ranges from 0 -> size as the buffer fills (remains at size once the buffer is full)
134  UInt_t nextElement; // indexes where we will insert the next element, the
135  std::vector<double> elements; // this will be a vector of (size+1) so that .end() iterator can use normal iterator!=RingBuffer::end() syntax for loops.
136 
137  // helper function
138  inline UInt_t oldestElement() const{
139  // if we haven't completely filled the buffer, then the oldest element is zero
140  UInt_t oldestElement = 0;
141  if(numRingElements==fSize){ // if we have filled the buffer,
142  // then the oldest is the one in front of the nextElement
143  oldestElement = nextElement + 1;
144  oldestElement = oldestElement >= fSize + 1? oldestElement - (fSize + 1) : oldestElement;
145  }
146  return oldestElement;
147  }
148 
149 };
150 
151 
152 #endif