循环写入读取的原理:在分配的指定大小的内存空间上,首地址开始写入,超出范围之后(未超出整体范围,只是超出当前写入位置之后整体范围的剩余范围)连接超出的范围到缓存的首地址(因为之前的数据比较早,已经被读取),如此循环。
剪切写入读取的原理:在分配的指定大小的内存空间上,首地址开始写入,写入超出整体之后提示报错(缓存空间不足),未超出则正常写入,读取数据时,从当前写位置开始往前读取,读取完之后,将读取的数据从缓存数据中剪切走(将写指针往前指向读的数据长度)。
以下是两种方式的源文件和头文件:(其中还包括线程锁函数)
void *CLoopBuffer::InitLoopBuffer(unsigned long buff_len)
{
LOOP_BUFFER * lb;
lb =new LOOP_BUFFER();
if( lb!=NULL )
{
lb->MaxLength = buff_len;
lb->Buffer =new unsigned char[buff_len];
if (lb->Buffer==NULL)
{
delete lb;
return NULL;
}
lb_ptr = lb;
ResetLoopBuffer();
}
return (void *)lb;
}
void CLoopBuffer::UnLockLoopBuffer()
{
BufferLock.UnLock();
}
void CLoopBuffer::LockLoopBuffer()
{
BufferLock.Lock();
}
void CLoopBuffer::FreeLoopBuffer()
{
LOOP_BUFFER * lb = (LOOP_BUFFER *)lb_ptr;
lb->WritePtr = NULL;
lb->ReadPtr = NULL;
delete []lb->Buffer;
delete lb ;
return;
}
void CLoopBuffer::ResetLoopBuffer()
{
LOOP_BUFFER * lb = (LOOP_BUFFER *)lb_ptr;
lb->CurWritePos = 0;
lb->WritePtr = lb->Buffer;
lb->CurReadPos = 0;
lb->ReadPtr = lb->Buffer;
UnLockLoopBuffer();
}
//取缓冲的写指针位置,该函数与WriteLoopBuffer配合使用来控制缓冲区的锁问题
//即:GetLoopBufferWritePos 置锁
// WriteLoopBuffer 写好后开锁
long CLoopBuffer::GetLoopBufferWritePos()
{
LOOP_BUFFER * lb = (LOOP_BUFFER *)lb_ptr;
LockLoopBuffer();
return lb->CurWritePos;
}
long CLoopBuffer::WriteLoopBuffer(unsigned char *data,long len)
{
try{
LOOP_BUFFER * lb = (LOOP_BUFFER *)lb_ptr;
unsigned char *ptr = lb->WritePtr,*s_ptr;
long r_len,l_len;
if( len + lb->CurWritePos > lb->MaxLength ) //buffer need loop
{
if( len < lb->MaxLength) //added 20080325
{
r_len = lb->MaxLength - lb->CurWritePos;
l_len = len - r_len;
s_ptr=data;
memcpy( ptr , s_ptr , r_len);
s_ptr += r_len;
ptr = lb->Buffer;
memcpy( ptr , s_ptr , l_len);
lb->WritePtr = lb->Buffer;
lb->WritePtr += l_len;
lb->CurWritePos =l_len;
}
else
myTRACE(1,3,"WriteLoopBuffer len is Error !\n");
}
else { //buffer right enought for write,not loop
memcpy( ptr , data , len );
lb->WritePtr += len;
lb->CurWritePos +=len;
}
}
catch(...)
{
myTRACE(1,3,"WriteLoopBuffer Error !\n");
}
UnLockLoopBuffer();
return len;
}
//取缓冲中的数据,独立开、关锁
long CLoopBuffer::GetLoopBufferData(long readpos, char *tagdata , long requestlen )
{
if(requestlen<0)
return -1;
LOOP_BUFFER * lb = (LOOP_BUFFER *)lb_ptr;
long pos=0,l_len=0,r_len=0;
LockLoopBuffer();
try{
if( readpos >= lb->MaxLength )
pos = readpos % lb->MaxLength;
else
pos = readpos;
char* ptr = (char *)lb->Buffer;
ptr += pos;
if( pos + requestlen > lb->MaxLength )
{
if( requestlen < lb->MaxLength) //added 20080325
{
r_len = lb->MaxLength - pos;
l_len = requestlen - r_len;
memcpy( tagdata , ptr , r_len );
tagdata += r_len ;
ptr = (char *)lb->Buffer;
memcpy( tagdata , ptr , l_len );
}
else
myTRACE(1,3,"GetLoopBufferData requestlen is Error !\n");
}
else
{
memcpy( tagdata , ptr , requestlen );
}
}
catch(...)
{
myTRACE(1,3,"GetLoopBufferData Error !\n");
requestlen =-1;
}
UnLockLoopBuffer();
return requestlen;
}
#if !defined(LOOP_BUFFER__H)
#define LOOP_BUFFER__H
#include "ThreadLock.h"
typedef struct {
long PacketPos; //this media packet position on MediaBuffer
long PacketLenfth; //this media packet length
}PACKET_PARSE;
typedef struct {
long MaxLength;
long CurWritePos;
long CurReadPos;
unsigned char *Buffer;
unsigned char *ReadPtr;
unsigned char *WritePtr;
}LOOP_BUFFER;
class CLoopBuffer
{
public:
void *InitLoopBuffer(unsigned long buff_len);
void FreeLoopBuffer();
long WriteLoopBuffer(unsigned char *data,long len);
void ResetLoopBuffer();
long GetLoopBufferWritePos();
long GetLoopBufferData(long readpos, char *tagdata , long requestlen );
//char *GetLoopBufferAviliDataPtr(long startpos,long requestlen,long *ret_len);
//void GetLoopBufferAviliDataPtrEnd();
void LockLoopBuffer();
void UnLockLoopBuffer();
void *lb_ptr;
private :
CThreadLock BufferLock;
};
#endif
void *CCutBuffer::InitCutBuffer(long buff_len)
{
CUT_BUFFER * cb;
cb = new CUT_BUFFER();
cb->MaxLength = buff_len;
cb->Buffer = new char[buff_len];
memset(cb->Buffer,0,buff_len);
cb->CurWritePos = 0;
cb->WritePtr = cb->Buffer;
cb_ptr = (void *)cb;
return (void *)cb;
}
void CCutBuffer::FreeCutBuffer()
{
CUT_BUFFER * cb = (CUT_BUFFER *)cb_ptr;
cb->WritePtr = NULL;
delete []cb->Buffer;
delete cb;
return;
}
void CCutBuffer::LockCutBuffer()
{
BufferLock.Lock();
}
void CCutBuffer::UnLockCutBuffer()
{
BufferLock.UnLock();
}
long CCutBuffer::WriteCutBuffer(unsigned char *data,long len)
{
CUT_BUFFER * cb = (CUT_BUFFER *)cb_ptr;
if(len<=0 || len> cb->MaxLength) //added 20080325
{
myTRACE(1,3,"WriteCutBuffer len is Error !\n");
return -1;
}
BufferLock.Lock();
unsigned char *ptr = (unsigned char *)cb->WritePtr;
if( len + cb->CurWritePos > cb->MaxLength ) //buffer not enought for write
{
myTRACE(0,3,"WriteCutBuffer buffer not enought for write,Clear the Buffer \n");
cb->CurWritePos = 0;
cb->WritePtr = cb->Buffer;
BufferLock.UnLock();
return -1;
}
else //buffer right enought for write,not loop
{
memcpy( ptr , data , len );
cb->WritePtr += len;
cb->CurWritePos +=len;
}
BufferLock.UnLock();
return len;
}
unsigned char *CCutBuffer::GetCutBufferWritePtr(long *len)
{
CUT_BUFFER * cb = (CUT_BUFFER *)cb_ptr;
BufferLock.Lock();
long al = cb->MaxLength - cb->CurWritePos;
*len = al;
if( al <= 0 )
{
BufferLock.UnLock();
}
return (unsigned char *)cb->WritePtr;
}
void CCutBuffer::UpdateCutBufferWrite(long len)
{
if( len <= 0 ) {
BufferLock.UnLock();
return;
}
CUT_BUFFER * cb = (CUT_BUFFER *)cb_ptr;
cb->CurWritePos += len;
cb->WritePtr += len;
BufferLock.UnLock();
}
unsigned char *CCutBuffer::GetCutBufferReadPtr(long *len)
{
CUT_BUFFER * cb = (CUT_BUFFER *)cb_ptr;
BufferLock.Lock();
*len = cb->CurWritePos;
if( cb->CurWritePos <= 0 )
{
cb->CurWritePos = 0;
cb->WritePtr = cb->Buffer; //added 20080325
BufferLock.UnLock();
}
return (unsigned char *)cb->Buffer;
}
void CCutBuffer::UpdateCutBufferRead(long len)
{
if( len <= 0 ) {
BufferLock.UnLock();
return;
}
CUT_BUFFER * cb = (CUT_BUFFER *)cb_ptr;
if( cb->CurWritePos > len ) {
unsigned char* sptr = (unsigned char *)cb->Buffer;
unsigned char* tptr = (unsigned char *)cb->Buffer;
sptr += len;
memcpy( tptr , sptr , cb->CurWritePos - len );//memmove保险些,memcpy效率高些
}
cb->CurWritePos -= len;
cb->WritePtr -= len;
BufferLock.UnLock();
}
void CCutBuffer::ResetCutBuffer()
{
CUT_BUFFER * cb = (CUT_BUFFER *)cb_ptr;
cb->CurWritePos = 0;
cb->WritePtr = cb->Buffer;
BufferLock.UnLock();
}
bool CCutBuffer::NoData()
{
CUT_BUFFER * cb = (CUT_BUFFER *)cb_ptr;
if( cb->CurWritePos == 0 )
return true;
return false;
}
#if !defined(CUT_BUFFER_H)
#define CUT_BUFFER_H
#include "ThreadLock.h"
typedef struct {
long MaxLength;
long CurWritePos;
char *Buffer;
char *WritePtr;
}CUT_BUFFER;
class CCutBuffer
{
public:
void LockCutBuffer();
void UnLockCutBuffer();
void *InitCutBuffer(long buff_len);
void FreeCutBuffer();
long WriteCutBuffer(unsigned char *data,long len);
//long DirectWriteCutBuffer(unsigned char *data,long len);
unsigned char *GetCutBufferWritePtr(long *len);
void UpdateCutBufferWrite(long len);
unsigned char *GetCutBufferReadPtr(long *len);
void UpdateCutBufferRead(long len);
void ResetCutBuffer();
bool NoData();
void *cb_ptr;
private:
CThreadLock BufferLock;
};
#endif
#include "StdAfx.h"
#include "ThreadLock.h"
//#include "stream_svr.h"
CThreadLock::CThreadLock(void)
{
#ifdef WIN32
ThreadLockHandle = CreateMutex (NULL, FALSE, NULL);
#else
pthread_mutex_init(&ThreadLockHandle,NULL);
#endif
}
CThreadLock::~CThreadLock(void)
{
#ifdef WIN32
CloseHandle(ThreadLockHandle);
#else
pthread_mutex_destroy(&ThreadLockHandle);
#endif
}
void CThreadLock::Lock()
{
#ifdef WIN32
WaitForSingleObject(ThreadLockHandle, INFINITE);
#else
pthread_mutex_lock(&ThreadLockHandle);
#endif
}
void CThreadLock::UnLock()
{
#ifdef WIN32
ReleaseMutex(ThreadLockHandle);
#else
pthread_mutex_unlock(&ThreadLockHandle);
#endif
}
#ifndef THREAD_LOCK_H
#define THREAD_LOCK_H
//#include "stream_svr.h"
#ifndef WIN32
#include <pthread.h>
#endif
class CThreadLock
{
public:
CThreadLock(void);
~CThreadLock(void);
void Lock();
void UnLock();
#ifdef WIN32
HANDLE ThreadLockHandle;
#else
pthread_mutex_t ThreadLockHandle;
#endif
};
#endif