环形缓冲区。我的理解就是,开辟一块内存区域,然后会有操作不断地往里边存放数据,同时也会有操作从这块区域里边往外拿数据。主要用在网络编程中,数据接收线程接收客户端发送过来的数据,先存放到环形缓冲区中,然后数据处理线程再从里边逐条读取数据并处理。实现的重点有两点:1、保证存放数据的时候不会覆盖还未读取的数据、读取数据的时候不会重复读取已经读取过的数据;2、线程同步。
下面是我实现的一个简单的环形缓冲区代码:
#ifndef __rbuf_h__
#define __rbuf_h__
#include <Windows.h>
class RBuf
{
public:
RBuf ( int sz );
~RBuf ();
bool init ();
bool initOk ();
bool empty ();
bool full ();
bool read ( char *data, int len );
bool write ( const char *data, int len );
void destroy ();
private:
CRITICAL_SECTION m_cs;
int m_sz;
int m_rpos;
int m_wpos;
char *m_buf;
bool m_bOk;
};
#endif // __rbuf_h__
#include "rbuf.h"
RBuf::RBuf( int sz )
: m_sz( sz )
, m_rpos( 0 )
, m_wpos( 0 )
, m_buf( NULL )
, m_bOk( false )
{
InitializeCriticalSection( &m_cs );
init();
}
RBuf::~RBuf()
{
destroy();
DeleteCriticalSection( &m_cs );
}
bool RBuf::init()
{
destroy();
EnterCriticalSection( &m_cs );
m_buf = new char[m_sz];
if( NULL == m_buf )
m_bOk = false;
else {
memset( m_buf, 0, sizeof(char) * m_sz );
m_bOk = true;
m_rpos = 0;
m_wpos = 0;
}
LeaveCriticalSection( &m_cs );
return m_bOk;
}
void RBuf::destroy()
{
EnterCriticalSection( &m_cs );
if( NULL != m_buf ) {
delete []m_buf;
m_buf = NULL;
}
LeaveCriticalSection( &m_cs );
}
bool RBuf::initOk()
{
return m_bOk;
}
bool RBuf::empty()
{
bool bret = false;
EnterCriticalSection( &m_cs );
if( m_rpos == m_wpos )
bret = true;
LeaveCriticalSection( &m_cs );
return bret;
}
bool RBuf::full()
{
bool bret = false;
EnterCriticalSection( &m_cs );
if( (m_wpos + 1) == m_rpos )
bret = true;
else if( (m_rpos == 0) && (m_wpos == (m_sz - 1)) )
bret = true;
LeaveCriticalSection( &m_cs );
return bret;
}
bool RBuf::read( char *data, int len )
{
if( empty() )
return false;
bool bret = false;
EnterCriticalSection( &m_cs );
if( m_rpos < m_wpos ) {
if( m_wpos - m_rpos < len )
bret = false;
else {
memcpy( data, m_buf + m_rpos, len );
m_rpos += len;
bret = true;
}
}
else {
if( m_sz - m_rpos >= len ) {
memcpy( data, m_buf + m_rpos, len );
m_rpos += len;
if( m_rpos == m_sz )
m_rpos = 0;
bret = true;
}
else {
int len1 = m_sz - m_rpos;
if( m_wpos + len1 >= len ) {
memcpy( data, m_buf + m_rpos, len1 );
memcpy( data + len1, m_buf, len - len1 );
m_rpos = len - len1;
bret = true;
}
else
bret = false;
}
}
LeaveCriticalSection( &m_cs );
return bret;
}
bool RBuf::write( const char *data, int len )
{
if( full() )
return false;
bool bret = false;
EnterCriticalSection( &m_cs );
if( m_wpos < m_rpos ) {
if( m_rpos - m_wpos < len )
bret = false;
else {
memcpy( m_buf + m_wpos, data, len );
m_wpos += len;
bret = true;
}
}
else {
if( m_sz - m_wpos >= len ) {
memcpy( m_buf + m_wpos, data, len );
m_wpos += len;
if( m_wpos == m_sz )
m_wpos = 0;
bret = true;
}
else {
int len1 = m_sz - m_wpos;
if( m_rpos + len1 > len ) {
memcpy( m_buf + m_wpos, data, len1 );
memcpy( m_buf, data + len1, len - len1 );
m_wpos = len - len1;
bret = true;
}
else
bret = false;
}
}
LeaveCriticalSection( &m_cs );
return bret;
}
下面是简单的测试代码以及测试结果:
#include "rbuf.h"
#include <stdio.h>
#include <time.h>
#include <string>
using namespace std;
typedef enum _em_data_type {
dtInt,
dtStr,
dtSt,
dtCount
} DataType;
typedef struct _st_data_header {
DataType dt;
int len;
} DataHeader;
typedef struct _st_st {
char c;
float f;
char s[128];
} St;
DWORD WINAPI readProc ( LPVOID param );
DWORD WINAPI writeProc ( LPVOID param );
bool readData ( RBuf *pbuf );
bool writeData ( RBuf *pbuf, DataType dt );
int main( void )
{
RBuf rbuf( 1024 );
if( !rbuf.initOk() ) {
printf( "init rbuf failed\r\n" );
return -1;
}
else
printf( "init rbuf success\r\n" );
HANDLE hWrite = CreateThread( NULL, 0, writeProc, &rbuf, 0, NULL );
if( NULL == hWrite ) {
printf( "create write thread failed\r\n" );
return -1;
}
Sleep( 10 );
HANDLE hRead = CreateThread( NULL, 0, readProc, &rbuf, 0, NULL );
if( NULL == hRead ) {
printf( "create read thread failed\r\n" );
CloseHandle( hWrite );
return -1;
}
WaitForSingleObject( hWrite, INFINITE );
WaitForSingleObject( hRead, INFINITE );
return 0;
}
DWORD WINAPI writeProc( LPVOID param )
{
srand( (unsigned)time(NULL) );
RBuf *pbuf = (RBuf*)param;
for( int i = 0; i < 128; i++ ) {
writeData( pbuf, (DataType)(i % dtCount) );
Sleep( 1 );
}
return 0;
}
DWORD WINAPI readProc( LPVOID param )
{
RBuf *pbuf = (RBuf*)param;
int count = 0;
while( 1 ) {
if( count > 5 )
break;
if( readData(pbuf) ) {
count = 0;
Sleep( 1 );
}
else {
count++;
Sleep( 10 );
}
}
return 0;
}
bool writeData( RBuf *pbuf, DataType dt )
{
if( NULL == pbuf )
return false;
int valueInt = rand();
char valueStr[128] = { 0 };
St valueSt = { 0 };
DataHeader header;
header.dt = dt;
switch( dt )
{
case dtInt:
header.len = sizeof( int );
break;
case dtStr:
{
sprintf_s( valueStr, 128, "dtStr make random data %d", valueInt );
header.len = strlen(valueStr) + 1;
}
break;
case dtSt:
{
valueSt.c = rand() % 26 + 'a';
valueSt.f = (float)valueInt / 10;
sprintf_s( valueSt.s, 128, "dtSt make random data %d", valueInt );
header.len = sizeof( St );
}
break;
default:
printf( "write data get incorrect data type\r\n" );
return false;
}
char *data = new char[sizeof(DataHeader) + header.len];
memcpy( data, &header, sizeof(DataHeader) );
switch( dt ) {
case dtInt:
memcpy( data + sizeof(DataHeader), &valueInt, header.len );
break;
case dtStr:
memcpy( data + sizeof(DataHeader), &valueStr, header.len );
break;
case dtSt:
memcpy( data + sizeof(DataHeader), &valueSt, header.len );
break;
}
if( !pbuf->write(data, sizeof(DataHeader) + header.len) ) {
printf( "write data failed\r\n" );
delete []data;
return false;
}
else {
switch( dt ) {
case dtInt:
printf( "write dtInt data: %d\r\n", valueInt );
break;
case dtStr:
printf( "write dtStr data: %s\r\n", valueStr );
break;
case dtSt:
printf( "write dtSt data: %c, %f, %s\r\n", valueSt.c, valueSt.f, valueSt.s );
break;
}
delete []data;
return true;
}
}
bool readData( RBuf *pbuf )
{
if( NULL == pbuf )
return false;
DataHeader header;
if( !pbuf->read((char*)&header, sizeof(DataHeader)) )
return false;
char *data = new char[header.len];
if( !pbuf->read(data, header.len) ) {
delete []data;
return false;
}
switch( header.dt ) {
case dtInt:
printf( "read dtInt data: %d\r\n", *((int*)data) );
break;
case dtStr:
printf( "read dtStr data: %s\r\n", data );
break;
case dtSt:
{
St *pst = (St*)data;
printf( "read dtSt data: %c, %f, %s\r\n", pst->c, pst->f, pst->s );
}
break;
default:
printf( "read unknown data\r\n" );
}
delete []data;
return true;
}
init rbuf success
write dtInt data: 20471
write dtStr data: dtStr make random data 14713
write dtSt data: y, 1013.099976, dtSt make random data 10131
write dtInt data: 19480
write dtStr data: dtStr make random data 13095
write dtSt data: d, 3112.600098, dtSt make random data 31126
read dtInt data: 20471
write dtInt data: 5836
read dtStr data: dtStr make random data 14713
write dtStr data: dtStr make random data 16262
read dtSt data: y, 1013.099976, dtSt make random data 10131
write dtSt data: a, 3181.699951, dtSt make random data 31817
read dtInt data: 19480
write dtInt data: 400
read dtStr data: dtStr make random data 13095
write dtStr data: dtStr make random data 15085
read dtSt data: d, 3112.600098, dtSt make random data 31126
write dtSt data: m, 2668.300049, dtSt make random data 26683
read dtInt data: 5836
write dtInt data: 15743
read dtStr data: dtStr make random data 16262
write dtStr data: dtStr make random data 9180
read dtSt data: a, 3181.699951, dtSt make random data 31817
write dtSt data: f, 1957.599976, dtSt make random data 19576
read dtInt data: 400
write dtInt data: 20515
read dtStr data: dtStr make random data 15085
write dtStr data: dtStr make random data 3206
read dtSt data: m, 2668.300049, dtSt make random data 26683
write dtSt data: y, 1894.000000, dtSt make random data 18940
read dtInt data: 15743
write dtInt data: 19083
read dtStr data: dtStr make random data 9180
write dtStr data: dtStr make random data 17804
read dtSt data: f, 1957.599976, dtSt make random data 19576
write dtSt data: i, 906.900024, dtSt make random data 9069
read dtInt data: 20515
write dtInt data: 30365
read dtStr data: dtStr make random data 3206
write dtStr data: dtStr make random data 9740
read dtSt data: y, 1894.000000, dtSt make random data 18940
write dtSt data: e, 2996.100098, dtSt make random data 29961
read dtInt data: 19083
write dtInt data: 28334
read dtStr data: dtStr make random data 17804
write dtStr data: dtStr make random data 5338
read dtSt data: i, 906.900024, dtSt make random data 9069
write dtSt data: n, 1046.099976, dtSt make random data 10461
read dtInt data: 30365
write dtInt data: 21328
read dtStr data: dtStr make random data 9740
write dtStr data: dtStr make random data 14093
read dtSt data: e, 2996.100098, dtSt make random data 29961
write dtSt data: i, 3154.300049, dtSt make random data 31543
read dtInt data: 28334
write dtInt data: 4971
read dtStr data: dtStr make random data 5338
write dtStr data: dtStr make random data 26558
read dtSt data: n, 1046.099976, dtSt make random data 10461
write dtSt data: z, 905.500000, dtSt make random data 9055
read dtInt data: 21328
write dtInt data: 31376
read dtStr data: dtStr make random data 14093
write dtStr data: dtStr make random data 23820
read dtSt data: i, 3154.300049, dtSt make random data 31543
write dtSt data: u, 2982.600098, dtSt make random data 29826
read dtInt data: 4971
write dtInt data: 31113
read dtStr data: dtStr make random data 26558
write dtStr data: dtStr make random data 7779
read dtSt data: z, 905.500000, dtSt make random data 9055
write dtSt data: w, 279.899994, dtSt make random data 2799
read dtInt data: 31376
write dtInt data: 23861
read dtStr data: dtStr make random data 23820
write dtStr data: dtStr make random data 12287
read dtSt data: u, 2982.600098, dtSt make random data 29826
write dtSt data: r, 2291.800049, dtSt make random data 22918
read dtInt data: 31113
write dtInt data: 26515
read dtStr data: dtStr make random data 7779
write dtStr data: dtStr make random data 6059
read dtSt data: w, 279.899994, dtSt make random data 2799
write dtSt data: r, 1111.599976, dtSt make random data 11116
read dtInt data: 23861
write dtInt data: 32540
read dtStr data: dtStr make random data 12287
write dtStr data: dtStr make random data 7887
read dtSt data: r, 2291.800049, dtSt make random data 22918
write dtSt data: e, 2816.399902, dtSt make random data 28164
read dtInt data: 26515
write dtInt data: 26710
read dtStr data: dtStr make random data 6059
write dtStr data: dtStr make random data 30121
read dtSt data: r, 1111.599976, dtSt make random data 11116
write dtSt data: n, 2229.899902, dtSt make random data 22299
read dtInt data: 32540
write dtInt data: 15782
read dtStr data: dtStr make random data 7887
write dtStr data: dtStr make random data 7131
read dtSt data: e, 2816.399902, dtSt make random data 28164
write dtSt data: w, 1520.300049, dtSt make random data 15203
read dtInt data: 26710
write dtInt data: 6501
read dtStr data: dtStr make random data 30121
write dtStr data: dtStr make random data 12838
read dtSt data: n, 2229.899902, dtSt make random data 22299
write dtSt data: n, 1053.099976, dtSt make random data 10531
read dtInt data: 15782
write dtInt data: 9783
read dtStr data: dtStr make random data 7131
write dtStr data: dtStr make random data 6517
read dtSt data: w, 1520.300049, dtSt make random data 15203
write dtSt data: n, 695.599976, dtSt make random data 6956
read dtInt data: 6501
write dtInt data: 2456
read dtStr data: dtStr make random data 12838
write dtStr data: dtStr make random data 797
read dtSt data: n, 1053.099976, dtSt make random data 10531
write dtSt data: f, 2254.300049, dtSt make random data 22543
read dtInt data: 9783
write dtInt data: 23736
read dtStr data: dtStr make random data 6517
write dtStr data: dtStr make random data 22115
read dtSt data: n, 695.599976, dtSt make random data 6956
write dtSt data: n, 2087.699951, dtSt make random data 20877
read dtInt data: 2456
write dtInt data: 10121
read dtStr data: dtStr make random data 797
write dtStr data: dtStr make random data 3903
read dtSt data: f, 2254.300049, dtSt make random data 22543
write dtSt data: b, 622.299988, dtSt make random data 6223
read dtInt data: 23736
write dtInt data: 4630
read dtStr data: dtStr make random data 22115
write dtStr data: dtStr make random data 31327
read dtSt data: n, 2087.699951, dtSt make random data 20877
write dtSt data: e, 1429.599976, dtSt make random data 14296
read dtInt data: 10121
write dtInt data: 16406
read dtStr data: dtStr make random data 3903
write dtStr data: dtStr make random data 29295
read dtSt data: b, 622.299988, dtSt make random data 6223
write dtSt data: k, 376.700012, dtSt make random data 3767
read dtInt data: 4630
write dtInt data: 2753
read dtStr data: dtStr make random data 31327
write dtStr data: dtStr make random data 664
read dtSt data: e, 1429.599976, dtSt make random data 14296
write dtSt data: z, 3046.500000, dtSt make random data 30465
read dtInt data: 16406
write dtInt data: 3298
read dtStr data: dtStr make random data 29295
write dtStr data: dtStr make random data 4678
read dtSt data: k, 376.700012, dtSt make random data 3767
write dtSt data: m, 2124.600098, dtSt make random data 21246
read dtInt data: 2753
write dtInt data: 13614
read dtStr data: dtStr make random data 664
write dtStr data: dtStr make random data 32303
read dtSt data: z, 3046.500000, dtSt make random data 30465
write dtSt data: q, 2102.699951, dtSt make random data 21027
read dtInt data: 3298
write dtInt data: 21204
read dtStr data: dtStr make random data 4678
write dtStr data: dtStr make random data 17041
read dtSt data: m, 2124.600098, dtSt make random data 21246
write dtSt data: a, 57.599998, dtSt make random data 576
read dtInt data: 13614
write dtInt data: 20565
read dtStr data: dtStr make random data 32303
write dtStr data: dtStr make random data 6842
read dtSt data: q, 2102.699951, dtSt make random data 21027
write dtSt data: s, 25.100000, dtSt make random data 251
read dtInt data: 21204
write dtInt data: 4246
read dtStr data: dtStr make random data 17041
write dtStr data: dtStr make random data 14798
read dtSt data: a, 57.599998, dtSt make random data 576
write dtSt data: s, 2495.699951, dtSt make random data 24957
read dtInt data: 20565
write dtInt data: 8756
read dtStr data: dtStr make random data 6842
write dtStr data: dtStr make random data 197
read dtSt data: s, 25.100000, dtSt make random data 251
write dtSt data: g, 676.299988, dtSt make random data 6763
read dtInt data: 4246
write dtInt data: 15639
read dtStr data: dtStr make random data 14798
write dtStr data: dtStr make random data 21939
read dtSt data: s, 2495.699951, dtSt make random data 24957
write dtSt data: u, 412.000000, dtSt make random data 4120
read dtInt data: 8756
write dtInt data: 15946
read dtStr data: dtStr make random data 197
write dtStr data: dtStr make random data 76
read dtSt data: g, 676.299988, dtSt make random data 6763
write dtSt data: y, 383.299988, dtSt make random data 3833
read dtInt data: 15639
write dtInt data: 5641
read dtStr data: dtStr make random data 21939
write dtStr data: dtStr make random data 12199
read dtSt data: u, 412.000000, dtSt make random data 4120
write dtSt data: n, 1903.300049, dtSt make random data 19033
read dtInt data: 15946
write dtInt data: 23580
read dtStr data: dtStr make random data 76
write dtStr data: dtStr make random data 3394
read dtSt data: y, 383.299988, dtSt make random data 3833
write dtSt data: g, 1313.300049, dtSt make random data 13133
read dtInt data: 5641
write dtInt data: 32356
read dtStr data: dtStr make random data 12199
write dtStr data: dtStr make random data 327
read dtSt data: n, 1903.300049, dtSt make random data 19033
write dtSt data: j, 1533.900024, dtSt make random data 15339
read dtInt data: 23580
write dtInt data: 15796
read dtStr data: dtStr make random data 3394
write dtStr data: dtStr make random data 3085
read dtSt data: g, 1313.300049, dtSt make random data 13133
write dtSt data: d, 2322.300049, dtSt make random data 23223
read dtInt data: 32356
write dtInt data: 27874
read dtStr data: dtStr make random data 327
write dtStr data: dtStr make random data 22754
read dtSt data: j, 1533.900024, dtSt make random data 15339
write dtSt data: s, 2518.199951, dtSt make random data 25182
read dtInt data: 15796
write dtInt data: 9757
read dtStr data: dtStr make random data 3085
write dtStr data: dtStr make random data 28168
read dtSt data: d, 2322.300049, dtSt make random data 23223
write dtSt data: q, 42.299999, dtSt make random data 423
read dtInt data: 27874
write dtInt data: 27264
read dtStr data: dtStr make random data 22754
write dtStr data: dtStr make random data 7677
read dtSt data: s, 2518.199951, dtSt make random data 25182
write dtSt data: z, 3267.800049, dtSt make random data 32678
read dtInt data: 9757
write dtInt data: 24552
read dtStr data: dtStr make random data 28168
write dtStr data: dtStr make random data 7679
read dtSt data: q, 42.299999, dtSt make random data 423
write dtSt data: x, 209.899994, dtSt make random data 2099
read dtInt data: 27264
write dtInt data: 8451
read dtStr data: dtStr make random data 7677
write dtStr data: dtStr make random data 26064
read dtSt data: z, 3267.800049, dtSt make random data 32678
read dtInt data: 24552
read dtStr data: dtStr make random data 7679
read dtSt data: x, 209.899994, dtSt make random data 2099
read dtInt data: 8451
read dtStr data: dtStr make random data 26064
请按任意键继续. . .