-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathringbuffer.h
More file actions
66 lines (59 loc) · 1.53 KB
/
ringbuffer.h
File metadata and controls
66 lines (59 loc) · 1.53 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
//
// ringbuffer.h
// rnes
//
//
#ifndef __RINGBUFFER_H__
#define __RINGBUFFER_H__
#include <cassert>
#include <condition_variable>
#include <cstdint>
#include <iostream>
#include <mutex>
#include <vector>
namespace Rnes {
static bool isPow2(uint32_t i) { return ((i - 1) & i) == 0; }
template <typename T> class RingBuffer {
std::vector<T> buffer;
uint32_t size;
volatile uint64_t get, put;
std::mutex mutex;
std::condition_variable consumeCv;
std::condition_variable produceCv;
bool hasData(uint32_t count) const { return (get + count) <= put; }
bool hasEmptySpace(uint32_t count) const { return (put + count - get) <= size; }
public:
RingBuffer(uint32_t sz)
: buffer(sz, 0), size{sz}, get{0}, put{0}, mutex{}, consumeCv{}, produceCv{} {
assert(isPow2(sz));
}
~RingBuffer() {}
void putData(const T *in, uint32_t count) {
{
std::unique_lock<std::mutex> lock(mutex);
if (!hasEmptySpace(count)) {
produceCv.wait(lock, [&] { return this->hasEmptySpace(count); });
}
for (uint32_t i = 0; i < count; i++) {
buffer[put & (size - 1)] = in[i];
put += 1;
}
}
consumeCv.notify_one();
}
void getData(T *out, uint32_t count) {
{
std::unique_lock<std::mutex> lock(mutex);
if (!hasData(count)) {
consumeCv.wait(lock, [&] { return this->hasData(count); });
}
for (uint32_t i = 0; i < count; i++) {
out[i] = buffer[get & (size - 1)];
get += 1;
}
}
produceCv.notify_one();
}
};
}; // namespace Rnes
#endif