104 lines
2.8 KiB
C++
104 lines
2.8 KiB
C++
#pragma once
|
||
|
||
#include <extra2d/core/types.h>
|
||
#include <atomic>
|
||
#include <array>
|
||
|
||
namespace extra2d {
|
||
|
||
/**
|
||
* @brief 无锁环形缓冲区(单生产者单消费者)
|
||
* @tparam T 元素类型
|
||
* @tparam Size 缓冲区大小(必须是2的幂)
|
||
*/
|
||
template <typename T, size_t Size>
|
||
class RingBuffer {
|
||
static_assert((Size & (Size - 1)) == 0, "Size must be a power of 2");
|
||
|
||
public:
|
||
RingBuffer() = default;
|
||
|
||
/**
|
||
* @brief 入队
|
||
* @param item 元素
|
||
* @return 成功返回true,缓冲区满返回false
|
||
*/
|
||
bool push(const T& item) {
|
||
const size_t currentHead = head_.load(std::memory_order_relaxed);
|
||
const size_t currentTail = tail_.load(std::memory_order_acquire);
|
||
|
||
if ((currentHead - currentTail) >= Size) {
|
||
return false; // 缓冲区满
|
||
}
|
||
|
||
buffer_[currentHead & mask_] = item;
|
||
head_.store(currentHead + 1, std::memory_order_release);
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* @brief 入队(移动语义)
|
||
* @param item 元素
|
||
* @return 成功返回true,缓冲区满返回false
|
||
*/
|
||
bool push(T&& item) {
|
||
const size_t currentHead = head_.load(std::memory_order_relaxed);
|
||
const size_t currentTail = tail_.load(std::memory_order_acquire);
|
||
|
||
if ((currentHead - currentTail) >= Size) {
|
||
return false; // 缓冲区满
|
||
}
|
||
|
||
buffer_[currentHead & mask_] = std::move(item);
|
||
head_.store(currentHead + 1, std::memory_order_release);
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* @brief 出队
|
||
* @param item 输出元素
|
||
* @return 成功返回true,缓冲区空返回false
|
||
*/
|
||
bool pop(T& item) {
|
||
const size_t currentTail = tail_.load(std::memory_order_relaxed);
|
||
const size_t currentHead = head_.load(std::memory_order_acquire);
|
||
|
||
if (currentTail == currentHead) {
|
||
return false; // 缓冲区空
|
||
}
|
||
|
||
item = std::move(buffer_[currentTail & mask_]);
|
||
tail_.store(currentTail + 1, std::memory_order_release);
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* @brief 检查是否为空
|
||
*/
|
||
bool empty() const {
|
||
return head_.load(std::memory_order_acquire) ==
|
||
tail_.load(std::memory_order_acquire);
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前大小
|
||
*/
|
||
size_t size() const {
|
||
return head_.load(std::memory_order_acquire) -
|
||
tail_.load(std::memory_order_acquire);
|
||
}
|
||
|
||
/**
|
||
* @brief 获取容量
|
||
*/
|
||
static constexpr size_t capacity() { return Size; }
|
||
|
||
private:
|
||
static constexpr size_t mask_ = Size - 1;
|
||
alignas(64) std::array<T, Size> buffer_;
|
||
alignas(64) std::atomic<size_t> head_{0};
|
||
alignas(64) std::atomic<size_t> tail_{0};
|
||
};
|
||
|
||
} // namespace extra2d
|