2023-01-18 16:34:17 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <atomic>
|
|
|
|
|
2023-01-21 08:54:30 +00:00
|
|
|
#define ARB_MAX_SIZE 255
|
2023-01-18 16:34:17 +00:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
class AtomicRingBuffer {
|
|
|
|
public:
|
|
|
|
T* get();
|
|
|
|
void increment_read();
|
2023-01-21 07:51:23 +00:00
|
|
|
bool try_put_and_increment_write(T item);
|
2023-01-18 16:34:17 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
size_t _read = 0;
|
|
|
|
size_t _write = 0;
|
2023-01-21 08:54:30 +00:00
|
|
|
std::atomic<unsigned char> _used = 0;
|
2023-01-18 16:34:17 +00:00
|
|
|
T _items[ARB_MAX_SIZE];
|
|
|
|
};
|
|
|
|
|
|
|
|
// function bodies must be in the header because https://stackoverflow.com/a/999383
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
T* AtomicRingBuffer<T>::get() {
|
|
|
|
if (this->_used.load() == 0) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return &this->_items[this->_read];
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
void AtomicRingBuffer<T>::increment_read() {
|
|
|
|
if (this->_used.load() == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
--this->_used;
|
|
|
|
this->_read = (this->_read + 1) % ARB_MAX_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2023-01-21 07:51:23 +00:00
|
|
|
bool AtomicRingBuffer<T>::try_put_and_increment_write(T item) {
|
|
|
|
if (this->_used.load() == ARB_MAX_SIZE) {
|
|
|
|
return false;
|
2023-01-18 16:34:17 +00:00
|
|
|
}
|
|
|
|
this->_items[this->_write] = std::move(item);
|
|
|
|
++this->_used;
|
|
|
|
this->_write = (this->_write + 1) % ARB_MAX_SIZE;
|
2023-01-21 07:51:23 +00:00
|
|
|
return true;
|
2023-01-18 16:34:17 +00:00
|
|
|
}
|