-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathringbuffer.h
More file actions
161 lines (130 loc) · 3.27 KB
/
ringbuffer.h
File metadata and controls
161 lines (130 loc) · 3.27 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
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
153
154
155
156
157
158
159
160
161
#ifndef RINGBUFFER_H
#define RINGBUFFER_H
#include <algorithm>
#include <memory.h>
//作为我们后面测试填入模板的具体类型进行测试,可忽略
struct Info{
u_int32_t timestamp;
double p;
u_int32_t v;
};
//环形缓存
template<typename T>
class ringbuffer {
public:
/**
* create a ringbuffer with space for up to size elements.
*/
explicit ringbuffer(size_t size)
: size(size)
, begin(0)
, end(0)
, wrap(false)
{
buffer = new T[size];
}
/**
* copy constructor
*/
ringbuffer(const ringbuffer<T> & rb)
{
this(rb.size);
begin = rb.begin;
end = rb.end;
memcpy(buffer, rb.buffer, sizeof(T) * size);
}
/**
* destructor
*/
~ringbuffer()
{
delete[] buffer;
}
size_t overWrite(const T * data, size_t n)
{
size_t sum = 0;
if(wrap){
while(n > 0){
size_t chunk_size = std::min(size - end, n);
memcpy(buffer + end, data, chunk_size * sizeof(T));
begin = (begin + chunk_size) % size;
end = (end + chunk_size) % size;
n -= chunk_size;
sum += chunk_size;
if(n > 0){
data += chunk_size;
}
}
}
return sum;
}
size_t write(const T * data, size_t n){
size_t sum = 0;
size_t chunk_size = std::min(size - end, n);
memcpy(buffer + end, data, chunk_size * sizeof(T));
end = (end + chunk_size) % size;
if(n <= chunk_size){
return n;
}
sum += chunk_size;
n -= chunk_size;
data += chunk_size;
chunk_size = std::min(begin, n);
memcpy(buffer + end, data, chunk_size * sizeof(T));
end = (end + chunk_size) % size;
sum += chunk_size;
if(end == begin){
n -= chunk_size;
wrap = true;
if(n > 0){
data += chunk_size;
sum += overWrite(data, n);
}
}
return sum;
}
size_t read(T * dest, size_t n)
{
n = std::min(n, getOccupied());
if (n == 0) {
return n;
}
if (wrap) {
wrap = false;
}
const size_t first_chunk = std::min(n, size - begin);
memcpy(dest, buffer + begin, first_chunk * sizeof(T));
begin = (begin + first_chunk) % size;
if (first_chunk < n) {
const size_t second_chunk = n - first_chunk;
memcpy(dest + first_chunk, buffer + begin, second_chunk * sizeof(T));
begin = (begin + second_chunk) % size;
}
return n;
}
size_t getOccupied() {
return wrap ? size : (end - begin + size) % size;
}
size_t getFree() {
return size - getOccupied();
}
size_t getBegin(){
return begin;
}
size_t getEnd(){
return end;
}
size_t getSize(){
return size;
}
const T& getNum(size_t pos){
return *(buffer+pos);
}
private:
T * buffer;
size_t size;
size_t begin;
size_t end;
bool wrap;
};
#endif // RINGBUFFER_H