利用我的前一篇文章介绍的多线程无锁解决方案,很容易实现一个支持一个线程读,一个线程写的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; };