关于连续内存的ring_buffer的无锁版本实现,待完善

basecoding 2018-03-28 12:34:12
要求:
设置固定大小的内存,以该版内存为依据,以ring_buffer形式,先实现单生产者,单消费者即可。
现在已经实现一部分,但是运行的时候,出现两个问题:
1)卡,貌似是死锁,
表现现象是:写线程write_buffer函数返回空,读线程Read_buffer总返回为空,
以致双方进入sleep,没有进入到正常读包状态。
事实上,buffer内是有数据可以读或写的。
2)读包长度异常。
表现现象是:写包长度<1500,但读包仍读出很大的一个数出来。
请各大神指引迷津,谢谢!

代码如下:
ringbuff.h文件
class RingBuffer 
{
public:
RingBuffer();
~RingBuffer();

//create ring buffer memory
void * CreateAsWriteReader(void * buffer, int bufLen);
void Destroy();

unsigned char *OpenWriteBuffer(int len);
void CloseWriterBuffer();

int ReadPacket(void **data);
void SkipToNextPacket();

private:
int Init(int bufLen);


RingBuffer(const RingBuffer &) {}
void operator=(const RingBuffer&) {}

private:
unsigned char *m_buffer;
unsigned int m_bufferLen;
volatile unsigned int m_readPos;
volatile unsigned int m_writePos;
volatile unsigned int m_newReadPos;
volatile unsigned int m_newWritePos;
};


ringbuff.cpp
#define RING_PKT_HEAD_LEN 4
static const int RING_BUFF_PKT_HEAD_LEN = 4;
RingBuffer::RingBuffer()
{
m_buffer = NULL;
m_bufferLen = 0;
m_readPos = 0;
m_writePos = 0;
m_newReadPos = 0;
m_newWritePos = 0;
}

RingBuffer::~RingBuffer()
{
Destroy();
}

void RingBuffer::Destroy()
{
if (m_buffer != NULL)
{
delete []m_buffer;
m_buffer = NULL;
}
}

void *RingBuffer::CreateAsWriteReader(void * buffer, int bufLen)
{
if (Init(6000) == 0)
return m_buffer;
else
return NULL;
}

int RingBuffer::Init(int bufferLen)
{
if (bufferLen <= RING_BUFF_PKT_HEAD_LEN)
return -2;

Destroy();
m_bufferLen = bufferLen;
m_buffer = new unsigned char[m_bufferLen];
if (m_buffer == NULL)
{
return -1;
}

m_readPos = 0;
m_writePos = 0;
m_newReadPos = 0;
m_newWritePos = 0;
return 0;
}

unsigned char* RingBuffer::OpenWriteBuffer(int len)
{
if (m_buffer == NULL || len <= 0)
return NULL;

unsigned int myReadPos = m_readPos;
unsigned int myWritePos = m_writePos;
unsigned int myNewWritePos = myWritePos + RING_BUFF_PKT_HEAD_LEN + len;
//buffer boundary
if(myNewWritePos >= m_bufferLen)
{
*(unsigned int *)(m_buffer+myWritePos) = 0x00;

//buffer full
if(RING_BUFF_PKT_HEAD_LEN + len >= myReadPos)
{
return NULL;
}

myWritePos = 0;
}

//buffer full
myNewWritePos = myWritePos + RING_BUFF_PKT_HEAD_LEN + len;
if(myWritePos < myReadPos && myNewWritePos >= myReadPos)
{
return NULL;
}

unsigned char *data = m_buffer + myWritePos;
*(unsigned int*)data = len;
m_newWritePos = myNewWritePos;

return data + RING_BUFF_PKT_HEAD_LEN;
}

void RingBuffer::CloseWriterBuffer()
{
if (m_buffer == NULL)
return;

m_writePos = m_newWritePos;
return;
}

int RingBuffer::ReadPacket(void **data)
{
if (data == NULL)
return 0;
*data = NULL;

//copy writePos
unsigned int myWritePos = m_writePos;
unsigned int myReadPos = m_readPos;
unsigned int myNewReadPos = myReadPos;
if(myReadPos == myWritePos)
{
return NULL;
}

//
unsigned char *bufferData = (m_buffer + myReadPos);
unsigned int len = *(unsigned int*)bufferData;
if(len == 0)
{
//buff empty
if (0 >= myWritePos)
{
return 0;
}

//
myReadPos = 0;
bufferData = (m_buffer);
len = *(unsigned int*)bufferData;
if(len==0)
{
printf("NG2");
}
}

if (len > 1600)
{
int i = 100;
}

//buff empty
myNewReadPos = myReadPos + RING_BUFF_PKT_HEAD_LEN + len;
if(myReadPos <= myWritePos && myNewReadPos >= myWritePos)
{
return 0;
}

//
m_newReadPos = myNewReadPos;
*data = bufferData + RING_BUFF_PKT_HEAD_LEN;
return len - RING_BUFF_PKT_HEAD_LEN;
}

void RingBuffer::SkipToNextPacket()
{
if (m_buffer == NULL)
return;

m_readPos = m_newReadPos;

return;
}
...全文
847 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
basecoding 2018-03-28
  • 打赏
  • 举报
回复
这个跟网上不太一样的地方就是,网上内存使用的是指针,然后在指针内部new内在,步长是1;这里的内存是连续的,一开始就申请好了。不做重新分配。,步长不固定。
赵4老师 2018-03-28
  • 打赏
  • 举报
回复
百度搜相关关键字。
basecoding 2018-03-28
  • 打赏
  • 举报
回复
求大神完善。急死,
basecoding 2018-03-28
  • 打赏
  • 举报
回复
求大神完善。急死,
donjin9 2018-03-28
  • 打赏
  • 举报
回复
要不先加个锁测试看看。。。

5,530

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 模式及实现
社区管理员
  • 模式及实现社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧