c++ 环形队列(RingBuffer)

发布于:2024-12-05 ⋅ 阅读:(100) ⋅ 点赞:(0)

环形缓冲区(Circular Buffer)与环形队列类似,是一种数据结构,支持在固定容量下的高效读写操作。相比队列,环形缓冲区通常允许覆盖旧数据,这在某些场景(如实时数据流、日志处理)中非常有用。

实现步骤

核心变量

  • 缓冲区数组 buffer[]:存储数据。
  • 读指针 head:指向下一个读取的位置。
  • 写指针 tail:指向下一个写入的位置。
  • 容量 capacity:缓冲区的总大小。
  • 当前大小 size:记录缓冲区中实际存储的数据个数(可选,用于非覆盖模式)。

操作方法

  • 写入数据(write):
    • 如果缓冲区未满,将数据写入 tail
    • 更新 tail(tail + 1) % capacity
    • 在覆盖模式下,若缓冲区已满,会覆盖最早的数据,并移动 head
  • 读取数据(read):
    • 如果缓冲区为空,读取失败。
    • head 读取数据,更新 head(head + 1) % capacity
  • 检查状态:
    • 缓冲区是否满:size == capacity
    • 缓冲区是否空:size == 0

代码示例(c++)

template <typename T>
class ZDThreadSafeCircularBuffer {
private:
    std::vector<T> buffer;            // 环形缓冲区
    int head;                         // 读指针
    int tail;                         // 写指针
    int capacity;                     // 缓冲区容量
    int size;                         // 当前缓冲区中元素的数量

    std::mutex mtx;                   // 互斥锁
    std::condition_variable notEmpty; // 缓冲区非空条件变量
    std::condition_variable notFull;  // 缓冲区非满条件变量

public:
    // 构造函数
    explicit ZDThreadSafeCircularBuffer(int capacity)
        : buffer(capacity), head(0), tail(0), capacity(capacity), size(0) {}

    // 写入数据
    void write(const T& value) {
        std::unique_lock<std::mutex> lock(mtx);
        notFull.wait(lock, [this]() { return size < capacity; }); // 等待缓冲区非满

        buffer[tail] = value;
        tail = (tail + 1) % capacity;
        ++size;

        notEmpty.notify_one(); // 通知有新数据可读
    }

    // 读取数据
    T read() {
        std::unique_lock<std::mutex> lock(mtx);
        notEmpty.wait(lock, [this]() { return size > 0; }); // 等待缓冲区非空

        T value = buffer[head];
        head = (head + 1) % capacity;
        --size;

        notFull.notify_one(); // 通知有新空间可写
        return value;
    }

    // 非阻塞写入
    bool tryWrite(const T& value) {
        std::lock_guard<std::mutex> lock(mtx);
        if (size >= capacity) {
            return false; // 缓冲区已满,写入失败
        }

        buffer[tail] = value;
        tail = (tail + 1) % capacity;
        ++size;

        notEmpty.notify_one(); // 通知有新数据可读
        return true;
    }

    // 非阻塞读取
    std::optional<T> tryRead() {
        std::lock_guard<std::mutex> lock(mtx);
        if (size == 0) {
            return std::nullopt; // 缓冲区为空,读取失败
        }

        T value = buffer[head];
        head = (head + 1) % capacity;
        --size;

        notFull.notify_one(); // 通知有新空间可写
        return value;
    }

    // 检查缓冲区是否为空
    bool isEmpty() const {
        std::lock_guard<std::mutex> lock(mtx);
        return size == 0;
    }

    // 检查缓冲区是否已满
    bool isFull() const {
        std::lock_guard<std::mutex> lock(mtx);
        return size == capacity;
    }

    // 获取缓冲区当前大小
    int getSize() const {
        std::lock_guard<std::mutex> lock(mtx);
        return size;
    }

    // 获取缓冲区容量
    int getCapacity() const {
        return capacity;
    }
};

网站公告

今日签到

点亮在社区的每一天
去签到