-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathringbuffer.hpp
More file actions
79 lines (64 loc) · 1.81 KB
/
ringbuffer.hpp
File metadata and controls
79 lines (64 loc) · 1.81 KB
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
#ifndef RINGBUFFER
#define RINGBUFFER_H
#include <iterator>
#include <vector>
#include <algorithm>
/* RingBuffer class
* Goals: provide an indexable queue that can support timestamp bisection
*/
template<class T>
class RingBuffer {
private:
size_t capacity; //Will always be a power of 2
size_t cap_min1; //Will always be one less than a power of 2
std::vector<T> _entries;
size_t head, tail;
//Relies on assumption that capacity is a positive power of 2
size_t wrap(size_t i) const {
return i & cap_min1;
}
void expand() {
std::vector<T> new_vect;
new_vect.resize(capacity*2);
if ( tail > head ) {
//Single range
std::copy(_entries.begin()+head, _entries.begin()+tail, new_vect.begin());
} else {
//Split range
std::copy(_entries.begin() + head, _entries.end(), new_vect.begin());
std::copy(_entries.begin(), _entries.begin() + tail, new_vect.begin() + (capacity - head));
}
tail = wrap(tail - head);
head = 0;
capacity = capacity*2;
cap_min1 = capacity-1;
_entries = std::move(new_vect);
}
public:
RingBuffer() : capacity(4), cap_min1(capacity-1), _entries(capacity),
head(3), tail(0) { _entries.resize(capacity); }
T& operator[](size_t index) {
return _entries.at( wrap(index+head) );
}
size_t size() const {
return ( wrap(tail - head) );
}
const T& operator[](size_t index) const {
return _entries.at( wrap(index+head) );
}
void advance() {
head = wrap(head-1);
tail = wrap(tail-1);
}
void extend() {
if (head == wrap(tail+1) ) {
expand();
}
head = wrap(head-1);
}
void append_to_head(const T& entry) {
extend();
_entries.at(head) = entry;
}
};
#endif