-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCircleMTIO.hpp
86 lines (64 loc) · 1.98 KB
/
CircleMTIO.hpp
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
#pragma once
#ifndef CIRCLEMTIO_HPP
#define CIRCLEMTIO_HPP
#include <array>
#include <atomic>
#include <mutex>
template <class T> struct __attribute__((aligned(64))) singlevarnofsh { T a; };
template <size_t num, class T> class __attribute__((aligned(64))) CircleMTIO {
std::array<T, num> elements;
std::array<singlevarnofsh<std::atomic<int>>, num> elements_state;
std::atomic<size_t> reading_point{};
std::atomic<size_t> writing_point{};
// std::atomic<size_t> read_point;
std::mutex mtx;
public:
using value_type = T;
using pair_t = std::pair<value_type, size_t>;
auto new_write() -> std::pair<T *, size_t> {
size_t a = writing_point.fetch_add(1);
if (a >= num) {
std::lock_guard<std::mutex> lck(mtx);
a = writing_point.fetch_add(1);
if (a >= num)
{
a = 0;
writing_point = 1;
}
}
if (elements_state[a].a != 0) {
return std::pair<T *, size_t>(nullptr, 0);
}
elements_state[a].a = 1;
return std::pair<T *, size_t>(&elements[a], a);
}
auto next() -> std::pair<T *, size_t> {
size_t r = reading_point;
if (elements_state[r].a != 2) {
return std::pair<T *, size_t>(nullptr, ~std::size_t(0));
}
if (r == writing_point) {
return std::pair<T *, size_t>(nullptr, ~std::size_t(0));
}
reading_point++;
if (reading_point >= num) {
reading_point = 0;
}
// read_point = r;
return std::pair<T *, size_t>(&elements[r], r);
}
void set_free(size_t a) {
elements_state[a].a = 0;
// read_point = ~std::size_t(0);
}
void set_ready(size_t a) { elements_state[a].a = 2; }
CircleMTIO() {
reading_point = 0;
writing_point = 0;
// read_point = ~std::size_t(0);
for (auto &b : elements_state) {
b.a = 0;
}
}
};
#endif