环形缓冲区由一个固定大小的数组构成,生产者将数据写入缓冲区的尾部,而消费者则从缓冲区的头部读取数据,当缓冲区被填满时,生产者会等待,直到有空间可用;当缓冲区为空时,消费者会等待,直到有数据可用
使用两个循环指针用来实现环形队列,头指针和尾指针在队列为空的时候是相同的,起始为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;
};
考虑并发生产和消费还需要加锁