环形buffer单生产单消费队列

2024-06-13 10:43:18 浏览数 (2)

环形缓冲区由一个固定大小的数组构成,生产者将数据写入缓冲区的尾部,而消费者则从缓冲区的头部读取数据,当缓冲区被填满时,生产者会等待,直到有空间可用;当缓冲区为空时,消费者会等待,直到有数据可用

使用两个循环指针用来实现环形队列,头指针和尾指针在队列为空的时候是相同的,起始为0,当头指针快追上尾指针的时候代表队列已满,也就是head=tail-1的时候,这意味着我们使用了一个元素的位置来表示队列是否满,环形buffer实际容量为数组长度减去一个单位

生产即入队,元素安排在头指针处,之后头指针移动,消费即出队,取尾指针处元素后移动尾指针

代码语言:javascript复制
template<typename T, std::size_t N>
class RingBuffQueue {
public:
    constexpr RingBuffQueue(): head(0), tail(0) {
    }

    // 如果满了返回false, 成功返回true
    bool enqueue(T val) {
        const int nextTail = (tail   1) % N;
        if (nextTail == head) {
            std::cout<<"full: "<<val<<std::endl;
            return false;
        }
        buff[tail] = val;
        tail = nextTail;
        std::cout << "product: " << val << std::endl;
        return true;
    }

    // 如果空返回nullopt, 成功返回队首元素
    std::optional<T> dequeue() {
        if (head == tail) {
            std::cout << "empty" << std::endl;
            return std::nullopt;
        }
        T response = buff[head];
        head = (head   1) % N;
        std::cout<<"consume: "<<response<<std::endl;
        return response;
    }

private:
    std::array<T, N> buff;
    size_t head;
    size_t tail;
};

考虑并发生产和消费还需要加锁

0 人点赞