环形队列可以通过维护count来间接维护tail和head指针的关系,简化程序,避免了直接使用tail和head指针,读写时head与tail回环时的比较处理, 判断队列元素长度时的复杂处理,如下为不基于count而是直接使用head和tail指针比较的环形队列的实现, 逻辑较为复杂
uint32_t CAudioRingBuffer::DataSizeLocked() const {
// 获取队列元素个数
if (m_isFull) {
return capacity;
} else {
return (m_writePos + capacity - m_readPos) % capacity;
}
}
void CAudioRingBuffer::setIsFull(bool reading) {
// 更新队列是否已满的状态
if (m_readPos == m_writePos) {
m_isFull = !reading;
} else {
m_isFull = false;
}
}
uint32_t CAudioRingBuffer::DoRead(char* outBuf, uint32_t wantSize) {
if (DataSizeLocked() <= 0) {
return 0;
}
if (m_writePos > m_readPos) {
// write指针在read指针右侧
uint32_t rSize = m_writePos - m_readPos;
if (rSize >= wantSize) {
//右的足够多,直接拷贝相关数据
rSize = wantSize;
} else {
//右的不够多,数组不足,将尾部数据补0
memset(outBuf + rSize, 0, wantSize - rSize);
}
memcpy(outBuf, &m_buf[m_readPos], rSize);
m_readPos += rSize;
setIsFull(true);
return rSize;
} else {
//write_pos <= m_readPos,写指针回环了
uint32_t headLen = 0;
uint32_t tailLen = m_sizeTotal - m_readPos; // 计算尾部区间有多少数据
if (tailLen >= wantSize) {
// 尾部区间数据足够,直接拷贝
tailLen = wantSize;
memcpy(outBuf, &m_buf[m_readPos], wantSize);
} else {
// 尾部区间不够的话,再算一下头部区间
memcpy(outBuf, &m_buf[m_readPos], tailLen);
headLen = m_writePos;
if (m_writePos > (wantSize - tailLen)) {
headLen = wantSize - tailLen;
} else {
// 头部区间还不够的话,再算一下需要补0的数
memset(outBuf + tailLen + headLen, 0, wantSize - tailLen - headLen);
}
memcpy(outBuf + tailLen, &m_buf[0], headLen);
}
uint32_t rTotal = headLen + tailLen;
m_readPos = (m_readPos + rTotal) % capacity;
setIsFull(true);
return rTotal;
}
}
基于count维护之后,此三个函数逻辑变得简化而直观
uint32_t CAudioRingBuffer::DataSizeLocked() const {
// 获取队列元素个数
return count;
}
void CAudioRingBuffer::setIsFull(bool reading) {
// 更新队列是否已满的状态
m_isFull = (count == capacity);
}
uint32_t CAudioRingBuffer::DoRead(char* outBuf, uint32_t wantSize) {
if (count <= 0) {
return 0;
}
int outBufOffset = 0;
int rSize, fillDataSize;
rSize = fillDataSize = (wantSize >= count ? count : wantSize);
int newReadPos = (readPos + fillDataSize) % capacity;
if ( fillDataSize > 0 && newReadPos <= m_readPos) {
// 处理回环
int rightDataSize = capacity - m_readPos;
memcpy(outBuf, &m_buf[m_readPos], rightDataSize);
m_readPos = 0;
outBufOffset += rightDataSize;
fillDataSize -= rightDataSize;
}
memcpy(outBuf + outBufOffset, &m_buf[m_readPos], fillDataSize);
outBufOffset += fillDataSize;
// 数据不足填0补充
int fiillZeroSize = wantSize - count;
if(fiillZeroSize > 0){
memset(outBuf + outBufOffset, 0, fiillZeroSize);
}
return rSize;
}
标签:count,outBuf,队列,readPos,c++,环形,wantSize,rSize,uint32
From: https://www.cnblogs.com/ishen/p/17562314.html