137 lines
3.6 KiB
C++
137 lines
3.6 KiB
C++
//
|
||
// Created by xtkuang on 2025/5/30.
|
||
//
|
||
|
||
#ifndef CMVR_ES_RING_BUFFER_H
|
||
#define CMVR_ES_RING_BUFFER_H
|
||
|
||
#pragma once
|
||
#include <deque>
|
||
#include <mutex>
|
||
#include <vector>
|
||
#include <atomic>
|
||
#include <optional>
|
||
|
||
template<typename T>
|
||
class RingBuffer {
|
||
public:
|
||
explicit RingBuffer(size_t capacity) : capacity_(capacity) {}
|
||
|
||
void push(const T& item) {
|
||
std::lock_guard<std::mutex> lock(mutex_);
|
||
if (buffer_.size() >= capacity_) {
|
||
buffer_.pop_front();
|
||
}
|
||
buffer_.push_back(item);
|
||
}
|
||
|
||
std::vector<T> getAll() const {
|
||
std::lock_guard<std::mutex> lock(mutex_);
|
||
return std::vector<T>(buffer_.begin(), buffer_.end());
|
||
}
|
||
|
||
void clear() {
|
||
std::lock_guard<std::mutex> lock(mutex_);
|
||
buffer_.clear();
|
||
}
|
||
|
||
size_t size() const {
|
||
std::lock_guard<std::mutex> lock(mutex_);
|
||
return buffer_.size();
|
||
}
|
||
|
||
private:
|
||
size_t capacity_;
|
||
std::deque<T> buffer_;
|
||
mutable std::mutex mutex_;
|
||
};
|
||
|
||
template<typename T>
|
||
class SPMCRingBuffer {
|
||
public:
|
||
explicit SPMCRingBuffer(size_t capacity)
|
||
: buffer_(capacity), capacity_(capacity),
|
||
head_(0), tail_(0) {}
|
||
|
||
// 写入操作(仅支持单个生产者)
|
||
void push(const T& item) {
|
||
size_t head = head_.load(std::memory_order_relaxed);
|
||
size_t tail = tail_.load(std::memory_order_acquire);
|
||
buffer_[head % capacity_] = item;
|
||
head = head + 1;
|
||
head_.store(head, std::memory_order_release);
|
||
if (head - tail >= capacity_) {
|
||
// 队列满,覆盖最旧的数据
|
||
tail_.store(tail + 1, std::memory_order_release);
|
||
}
|
||
}
|
||
|
||
// 单消费者使用(内部 tail_)
|
||
std::optional<T> pop() {
|
||
size_t tail = tail_.load(std::memory_order_relaxed);
|
||
size_t head = head_.load(std::memory_order_acquire);
|
||
if (tail >= head) return std::nullopt;
|
||
T value = buffer_[tail % capacity_];
|
||
tail_.store(tail + 1, std::memory_order_release);
|
||
return value;
|
||
}
|
||
|
||
std::optional<T> getLast() {
|
||
size_t tail = tail_.load(std::memory_order_relaxed);
|
||
size_t head = head_.load(std::memory_order_acquire);
|
||
if (tail >= head) return std::nullopt;
|
||
T value = buffer_[head_ % capacity_];
|
||
return value;
|
||
}
|
||
|
||
// 多消费者使用(每个读者独立维护 reader_tail)
|
||
std::optional<T> pop(size_t& reader_tail) const {
|
||
size_t head = head_.load(std::memory_order_acquire);
|
||
if (reader_tail >= head) return std::nullopt;
|
||
if (head > reader_tail + capacity_) {
|
||
// 数据已被覆盖,跳过无效读取区间
|
||
reader_tail = head - capacity_;
|
||
return std::nullopt;
|
||
}
|
||
T value = buffer_[reader_tail % capacity_];
|
||
reader_tail++;
|
||
return value;
|
||
}
|
||
|
||
size_t size() const {
|
||
return head_.load(std::memory_order_acquire) - tail_.load(std::memory_order_acquire);
|
||
}
|
||
|
||
size_t getHead() const {
|
||
return head_.load(std::memory_order_acquire);
|
||
}
|
||
|
||
size_t getTail() const {
|
||
return tail_.load(std::memory_order_acquire);
|
||
}
|
||
|
||
bool empty() const {
|
||
return size() == 0;
|
||
}
|
||
|
||
bool full() const {
|
||
return size() >= capacity_;
|
||
}
|
||
|
||
void clear() {
|
||
head_.store(0, std::memory_order_release);
|
||
tail_.store(0, std::memory_order_release);
|
||
}
|
||
|
||
private:
|
||
std::vector<T> buffer_;
|
||
const size_t capacity_;
|
||
|
||
std::atomic<size_t> head_; // 共享写指针
|
||
std::atomic<size_t> tail_; // 共享读指针(仅用于 SPSC 模式)
|
||
};
|
||
|
||
|
||
|
||
#endif //CMVR_ES_RING_BUFFER_H
|