/home/runner/work/HiCR/HiCR/include/hicr/frontends/channel/circularBuffer.hpp Source File

HiCR: /home/runner/work/HiCR/HiCR/include/hicr/frontends/channel/circularBuffer.hpp Source File
HiCR
circularBuffer.hpp
Go to the documentation of this file.
1/*
2 * Copyright 2025 Huawei Technologies Co., Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
24#pragma once
25
27
28namespace HiCR::channel
29{
30
42{
43 public:
44
52 CircularBuffer(size_t capacity, __volatile__ size_t *headAdvanceCounter, __volatile__ size_t *tailAdvanceCounter)
53 : _capacity(capacity),
54 _headAdvanceCounter(headAdvanceCounter),
55 _tailAdvanceCounter(tailAdvanceCounter)
56
57 {}
58
59 virtual ~CircularBuffer() = default;
60
72 [[nodiscard]] __INLINE__ size_t getHeadPosition() const noexcept { return *_headAdvanceCounter % _capacity; }
73
85 [[nodiscard]] __INLINE__ size_t getTailPosition() const noexcept { return *_tailAdvanceCounter % _capacity; }
86
99 __INLINE__ void advanceHead(const size_t n = 1, bool useCachedDepth = false)
100 {
101 // Current depth
102 const auto curDepth = useCachedDepth ? getCachedDepth() : getDepth();
103
104 // Calculating new depth
105 const auto newDepth = curDepth + n;
106
107 // Sanity check
108 if (newDepth > _capacity)
109 HICR_THROW_FATAL("New buffer depth (_depth (%lu) + n (%lu) = %lu) exceeded capacity (%lu) on increase. This is probably a bug in HiCR.\n", curDepth, n, newDepth, _capacity);
110
111 // Advance head
112 *_headAdvanceCounter = *_headAdvanceCounter + n;
113 }
114
121 __INLINE__ void advanceTail(const size_t n = 1)
122 {
123 // Current depth
124 const auto curDepth = getDepth();
125
126 // Sanity check
127 if (n > curDepth)
128 HICR_THROW_FATAL("Circular buffer depth (%lu) smaller than number of elements (%lu) to decrease on advance tail. This is probably a bug in HiCR.\n", curDepth, n);
129
130 // Advance tail
131 *_tailAdvanceCounter = *_tailAdvanceCounter + n;
132 }
133
141 [[nodiscard]] __INLINE__ size_t getCapacity() const noexcept { return _capacity; }
142
154 [[nodiscard]] __INLINE__ size_t getDepth() const noexcept { return calculateDepth(*_headAdvanceCounter, *_tailAdvanceCounter); }
155
161 void setCachedDepth(size_t depth) { _cachedDepth = depth; }
162
168 [[nodiscard]] __INLINE__ size_t getCachedDepth() const noexcept { return _cachedDepth; }
169
178 [[nodiscard]] __INLINE__ bool isFull() const noexcept { return getDepth() == _capacity; }
179
188 [[nodiscard]] __INLINE__ bool isEmpty() const noexcept { return *_headAdvanceCounter == *_tailAdvanceCounter; }
189
195 __INLINE__ void setHead(const size_t headAdvanceCounter)
196 {
197 // Sanity check
198 if (*_tailAdvanceCounter > headAdvanceCounter)
199 HICR_THROW_FATAL("Circular buffer new head advance value is smaller than tail's (%lu < %lu). This is probably a bug in HiCR.\n", headAdvanceCounter, *_tailAdvanceCounter);
200
201 // Calculating new depth
202 const auto newDepth = calculateDepth(headAdvanceCounter, *_tailAdvanceCounter);
203
204 // Sanity check
205 if (newDepth > _capacity) HICR_THROW_FATAL("Circular new buffer depth (%lu) exceeded capacity (%lu) on setHead. This is probably a bug in HiCR.\n", newDepth, _capacity);
206
207 // Setting head
208 *_headAdvanceCounter = headAdvanceCounter;
209 }
210
216 __INLINE__ void setTail(const size_t tailAdvanceCounter)
217 {
218 // Sanity check
219 if (tailAdvanceCounter > *_headAdvanceCounter)
220 HICR_THROW_FATAL("Circular buffer new tail advance value exceeds head (%lu > %lu). This is probably a bug in HiCR.\n", tailAdvanceCounter, *_headAdvanceCounter);
221
222 // Calculating new depth
223 const auto newDepth = calculateDepth(*_headAdvanceCounter, tailAdvanceCounter);
224
225 // Sanity check
226 if (newDepth > _capacity) HICR_THROW_FATAL("Circular buffer new buffer depth (%lu) exceeded capacity (%lu) on setTail. This is probably a bug in HiCR.\n", newDepth, _capacity);
227
228 // Setting head
229 *_tailAdvanceCounter = tailAdvanceCounter;
230 }
231
235 [[nodiscard]] __INLINE__ size_t getHeadAdvanceCounter() const noexcept { return *_headAdvanceCounter; }
236
240 [[nodiscard]] __INLINE__ size_t getTailAdvanceCounter() const noexcept { return *_tailAdvanceCounter; }
241
242 private:
243
247 const size_t _capacity;
248
252 __volatile__ size_t *const _headAdvanceCounter;
253
257 __volatile__ size_t *const _tailAdvanceCounter;
258
262 size_t _cachedDepth{0};
263
264 protected:
265
272 __INLINE__ static size_t calculateDepth(const size_t headAdvanceCounter, const size_t tailAdvanceCounter)
273 {
274 if (headAdvanceCounter < tailAdvanceCounter)
275 {
276 HICR_THROW_FATAL("Head index (%lu) < tail index (%lu). This is a critical bug in HiCR!\n", headAdvanceCounter, tailAdvanceCounter);
277 }
278 return headAdvanceCounter - tailAdvanceCounter;
279 }
280};
281
282} // namespace HiCR::channel
Generic class type for circular buffer.
Definition circularBuffer.hpp:42
__INLINE__ bool isEmpty() const noexcept
Definition circularBuffer.hpp:188
__INLINE__ size_t getCapacity() const noexcept
Definition circularBuffer.hpp:141
void setCachedDepth(size_t depth)
Definition circularBuffer.hpp:161
__INLINE__ size_t getHeadAdvanceCounter() const noexcept
Definition circularBuffer.hpp:235
__INLINE__ void setTail(const size_t tailAdvanceCounter)
Definition circularBuffer.hpp:216
__INLINE__ size_t getTailAdvanceCounter() const noexcept
Definition circularBuffer.hpp:240
__INLINE__ void advanceHead(const size_t n=1, bool useCachedDepth=false)
Definition circularBuffer.hpp:99
__INLINE__ size_t getDepth() const noexcept
Definition circularBuffer.hpp:154
static __INLINE__ size_t calculateDepth(const size_t headAdvanceCounter, const size_t tailAdvanceCounter)
Definition circularBuffer.hpp:272
__INLINE__ size_t getTailPosition() const noexcept
Definition circularBuffer.hpp:85
__INLINE__ void setHead(const size_t headAdvanceCounter)
Definition circularBuffer.hpp:195
__INLINE__ size_t getCachedDepth() const noexcept
Definition circularBuffer.hpp:168
CircularBuffer(size_t capacity, __volatile__ size_t *headAdvanceCounter, __volatile__ size_t *tailAdvanceCounter)
Definition circularBuffer.hpp:52
__INLINE__ void advanceTail(const size_t n=1)
Definition circularBuffer.hpp:121
__INLINE__ bool isFull() const noexcept
Definition circularBuffer.hpp:178
__INLINE__ size_t getHeadPosition() const noexcept
Definition circularBuffer.hpp:72
Provides a failure model and corresponding exception classes.
#define HICR_THROW_FATAL(...)
Definition exceptions.hpp:81