博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

环形缓冲

Posted on 2016-04-14 17:39  bw_0927  阅读(327)  评论(0)    收藏  举报

http://blog.csdn.net/soft2967/article/details/8744092

 

1.什么是环形缓冲区?
环形缓冲区一般是一段连续的buffer空间,空间可以是new或者使用vector<char>分配,这些空间对计算机来说是线性的,但我们在读取或者写入的时候需要%来计算读写的位置,
这样就抽象成环了。


2.什么时候用环形缓冲区
game的后台通常是几个程序来组成一个集群。这样几个后台进程必然需要通信。
比如下面一个简单的结构
 
 client--------- 接入层svr------logicsvr---------dbsvr


这样接入层在收到客户端数据包后需要把数据在发送给logicsvr,这样2个进程就需要通信 。进程间通信有多种方式,比如共享内存,socket方式等。
假如使用共享内存,那么2个进程如果读写而且还不用加锁(这里的读写是 一个只会去读数据,另一个只会去写数据)这个时候使用环形缓冲区就比较适合


下面是一个简单的实现 

 

 

[cpp] view plain copy
 
  1. #pragma once  
  2.   
  3. #include <vector>  
  4. #define QUEUERESERVELENGTH 8   //保留8个字节不用  
  5. #define MAX_BUF_LEN  0x7FF0  
  6. class CCricleBuffer  
  7. {  
  8. public:  
  9.     CCricleBuffer(unsigned int MaxLen);  
  10.     ~CCricleBuffer(void);  
  11.     //缓存区是否已满  
  12.     bool IsFull();  
  13.     //写入数据  
  14.     bool AppendBuffer(char* pBuffer, short len);  
  15.     //获得一个完整的packet  
  16.     bool GetPacket(char* pBuffer, short& TranLen, short MaxLen);  
  17. private:  
  18.     //获得缓存区剩余大小  
  19.     unsigned int GetRemain();  
  20. private:  
  21.     std::vector<char>  m_CricleBuf;  
  22.     unsigned int   m_Len;  
  23.     unsigned int   m_ActiveLen;  
  24.     unsigned int   m_ReadPos;  
  25.     unsigned int   m_WritePos;  
  26. };  



 

 

 

 

[cpp] view plain copy
 
    1. #include "StdAfx.h"  
    2. #include "CricleBuffer.h"  
    3.   
    4. CCricleBuffer::CCricleBuffer(unsigned int MaxLen)  
    5. {  
    6.   
    7.     m_Len = MaxLen;  
    8.     m_ActiveLen = MaxLen - QUEUERESERVELENGTH;  
    9.     m_ReadPos = 0;  
    10.     m_WritePos = 0;  
    11.     m_CricleBuf.resize(MaxLen);  
    12. }  
    13.   
    14. CCricleBuffer::~CCricleBuffer(void)  
    15. {  
    16. }  
    17.   
    18. unsigned int CCricleBuffer::GetRemain()  
    19. {  
    20.     unsigned int RemainLen = 0;  
    21.     if (m_ReadPos == m_WritePos)  
    22.     {  
    23.         RemainLen = m_Len;  
    24.     }  
    25.     else if (m_WritePos < m_ReadPos)  
    26.     {  
    27.         RemainLen = m_ReadPos - m_WritePos;  
    28.     }  
    29.     else  
    30.     {  
    31.         RemainLen = (m_Len - m_WritePos) + m_ReadPos;  
    32.     }  
    33.       
    34.     return RemainLen;  
    35. }  
    36.   
    37. bool CCricleBuffer::IsFull()  
    38. {  
    39.     unsigned int RemainLen = GetRemain();  
    40.     if (RemainLen - QUEUERESERVELENGTH > 0)  
    41.     {  
    42.         return false;  
    43.     }  
    44.     return true;  
    45. }  
    46.   
    47. bool CCricleBuffer::AppendBuffer(char* pBuffer, short len)  
    48. {  
    49.     if (pBuffer == NULL || len == 0)  
    50.     {  
    51.         //print log  
    52.         return false;  
    53.     }  
    54.       
    55.     if (m_ReadPos < 0 || m_ReadPos > m_Len ||  
    56.         m_WritePos <0 || m_WritePos > m_Len)  
    57.     {  
    58.         //print log  
    59.         return false;  
    60.     }  
    61.       
    62.     if (IsFull())  
    63.     {  
    64.         //print log  
    65.         return false;  
    66.     }  
    67.     unsigned int RemainLen = GetRemain() - QUEUERESERVELENGTH;  
    68.     if (len + sizeof(len) > RemainLen)  
    69.     {  
    70.         //print log  
    71.         return false;  
    72.     }  
    73.   
    74.     char* pDest = (char*)&len;  
    75.     int shortlen = sizeof(len);  
    76.     for (int i = 0; i < shortlen; ++i)  
    77.     {  
    78.         m_CricleBuf[m_WritePos] = pDest[i];  
    79.         m_WritePos = (m_WritePos + 1) % m_Len;  
    80.     }  
    81.   
    82.     if (m_WritePos < m_ReadPos)  
    83.     {  
    84.         memcpy((void*)&m_CricleBuf[m_WritePos],pBuffer,len);  
    85.     }  
    86.     else  
    87.     {  
    88.         if (m_Len - m_WritePos > len)  
    89.         {  
    90.             memcpy((void*)&m_CricleBuf[m_WritePos],(const void*)pBuffer,len);  
    91.         }  
    92.         else  
    93.         {  
    94.             //需要做2次copy  
    95.             unsigned int half = m_Len - m_WritePos;  
    96.             memcpy((void*)&m_CricleBuf[m_WritePos],(const void*)pBuffer,half);  
    97.             memcpy((void*)&m_CricleBuf[0],(const void*)pBuffer[half], len - half);  
    98.         }  
    99.     }  
    100.     m_WritePos = (m_WritePos + m_Len) % m_Len;    
    101.     return true;  
    102. }  
    103.   
    104. //pBuffer 输出缓存区瘦地址  
    105. //TranLen 实际的读取buffer长度  
    106. bool CCricleBuffer::GetPacket(char* pBuffer, short& TranLen, short MaxLen)  
    107. {  
    108.     if (NULL== pBuffer || MaxLen > MAX_BUF_LEN)  
    109.     {  
    110.         //print log  
    111.         return false;  
    112.     }  
    113.   
    114.     if (m_ReadPos < 0 || m_ReadPos > m_Len ||  
    115.         m_WritePos <0 || m_WritePos > m_Len)  
    116.     {  
    117.         //print log  
    118.         return false;  
    119.     }  
    120.   
    121.     if (IsFull())  
    122.     {  
    123.         //print log  
    124.         return false;  
    125.     }  
    126.   
    127.     unsigned int RemainLen = GetRemain() - QUEUERESERVELENGTH;  
    128.     if (RemainLen <= sizeof(short))  
    129.     {  
    130.         //print log  
    131.         return false;  
    132.     }  
    133.   
    134.     //读short长度,为后面一个完整的packet的长度  
    135.     unsigned int shortlen = sizeof(short);  
    136.     char* buff = (char*)&TranLen;  
    137.     for (int i = 0;i < shortlen; ++i)  
    138.     {  
    139.         buff[i] = m_CricleBuf[m_ReadPos];  
    140.         m_ReadPos = (m_ReadPos + 1) % m_Len;  
    141.     }  
    142.     //判断后面的长度是否有一个完整的packet      
    143.     if (RemainLen  - sizeof(short) <  TranLen || TranLen <=0)  
    144.     {  
    145.         //print log  
    146.         return false;  
    147.     }  
    148.   
    149.     if (m_ReadPos < m_WritePos)  
    150.     {  
    151.         memcpy((void*)pBuffer,(const void*)&m_CricleBuf[m_ReadPos],TranLen);  
    152.     }  
    153.     else  
    154.     {  
    155.         unsigned int half = m_Len - m_ReadPos;  
    156.         if (half > TranLen)  
    157.         {  
    158.             memcpy((void*)pBuffer,(const void*)&m_CricleBuf[m_ReadPos],TranLen);  
    159.         }  
    160.         else  
    161.         {  
    162.             memcpy((void*)pBuffer,(const void*)&m_CricleBuf[m_ReadPos],half);  
    163.             memcpy((void*)pBuffer[half],(const void*)&m_CricleBuf[0],TranLen-half);  
    164.         }  
    165.     }  
    166.     m_ReadPos = (m_ReadPos + TranLen) % m_Len;  
    167.     return true;  
    168. }