blob: fd8854a9a18a5d2c32977b0aa02f0d5e1fab69b4 (
plain) (
blame)
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
|
#pragma once
#include <yql/essentials/utils/yql_panic.h>
#include <util/system/yassert.h>
#include <util/generic/maybe.h>
#include <vector>
namespace NKikimr {
namespace NMiniKQL {
template<class T>
class TSafeCircularBuffer {
public:
TSafeCircularBuffer(TMaybe<size_t> size, T emptyValue, size_t initSize = 0)
: Buffer(size ? *size : initSize, emptyValue)
, EmptyValue(emptyValue)
, Unbounded(!size.Defined())
, Count(initSize)
{
if (!Unbounded) {
Y_ABORT_UNLESS(initSize <= *size);
}
}
bool IsUnbounded() const {
return Unbounded;
}
void PushBack(T&& data) {
if (Unbounded) {
Y_ABORT_UNLESS(Head + Count == Size());
Buffer.emplace_back(std::move(data));
} else {
YQL_ENSURE(!IsFull());
Buffer[RealIndex(Head + Count)] = std::move(data);
}
Count++;
MutationCount++;
}
const T& Get(size_t index) const {
if (index < Count) {
return Buffer[RealIndex(Head + index)];
} else {
// Circular buffer out of bounds
return EmptyValue;
}
}
void PopFront() {
if (!Count) {
// Circular buffer not have elements for pop, no elements, no problem
} else {
Buffer[Head] = EmptyValue;
Head = RealIndex(Head+1);
Count--;
}
MutationCount++;
}
size_t Size() const {
return Buffer.size();
}
size_t UsedSize() const {
return Count;
}
ui64 Generation() const {
return MutationCount;
}
void Clean() {
const auto usedSize = UsedSize();
for (size_t index = 0; index < usedSize; ++index) {
Buffer[RealIndex(Head + index)] = EmptyValue;
}
}
void Clear() {
Head = Count = 0;
Buffer.clear();
Buffer.shrink_to_fit();
}
private:
bool IsFull() const {
if (Unbounded) {
return false;
}
return UsedSize() == Size();
}
size_t RealIndex(size_t index) const {
auto size = Size();
Y_ABORT_UNLESS(size);
return index % size;
}
std::vector<T> Buffer;
const T EmptyValue;
const bool Unbounded;
size_t Head = 0;
size_t Count;
ui64 MutationCount = 0;
};
}
}
|