利用我的前一篇文章介绍的多线程无锁解决方案,很容易实现一个支持一个线程读,一个线程写的CycleBuffer。需要特别注意的是该CycleBuffer要求缓冲区长度为2的n次方。下面贴出代码:
class ZwAsynCount
{
public:
ZwAsynCount(unsigned uSize) //uSize必须为2的n次方
{
m_uReadCount = 0;
m_uWriteCount = 0;
m_uSize = uSize;
}
int Write(int nLen) //返回元素位置 -1表示读失败
{
int nRet = -1;
if (GetFree() >= nLen)
{
nRet = m_uWriteCount&(m_uSize-1);
}
return nRet;
}
void AddWrite(int nCount = 1)
{
m_uWriteCount += nCount;
}
int GetUsed()
{
return m_uWriteCount - m_uReadCount;
}
int GetFree()
{
return m_uSize - GetUsed();
}
int Read(int nLen) //返回元素位置 -1表示写失败
{
int nRet = -1;
if (GetUsed() <= nLen)
{
nRet = m_uReadCount&(m_uSize-1);
}
return nRet;
}
void AddRead(int nCount = 1)
{
m_uReadCount+= nCount;
}
private:
unsigned m_uSize;
volatile unsigned m_uReadCount;
volatile unsigned m_uWriteCount;
};
class CCycleBuffer
{
public:
CCycleBuffer(int nSize):m_asynCount(nSize)
{
m_pBuf = new char[nSize];
m_nTalLen = nSize;
}
int GetFreeSpace()
{
return m_asynCount.GetFree();
}
int GetLength()
{
return m_asynCount.GetUsed();
}
~CCycleBuffer()
{
if (m_pBuf)
{
delete m_pBuf;
}
}
bool Write(char* buf, int count)
{
bool bRet = false;
int nPos = m_asynCount.Write(count);
if (nPos >=0)
{
if (m_nTalLen - nPos >= count)
{
memcpy(m_pBuf + nPos, buf, count);
}
else
{
memcpy(m_pBuf + nPos, buf, m_nTalLen - nPos);
memcpy(m_pBuf, buf + m_nTalLen - nPos, count - (m_nTalLen - nPos));
}
m_asynCount.AddWrite(count);
bRet = true;
}
return bRet;
}
bool Read(char* buf, int count)
{
bool bRet = false;
int nPos = m_asynCount.Read(count);
if (nPos >=0)
{
if (m_nTalLen - nPos >= count)
{
memcpy(buf,m_pBuf + nPos,count);
}
else
{
memcpy(buf,m_pBuf + nPos, m_nTalLen - nPos);
memcpy(buf + m_nTalLen - nPos,m_pBuf, count - (m_nTalLen - nPos));
}
m_asynCount.AddRead(count);
bRet = true;
}
return bRet;
}
private:
char *m_pBuf;
int m_nTalLen;
ZwAsynCount m_asynCount;
};