211 lines
4.8 KiB
C++
211 lines
4.8 KiB
C++
#ifndef HGL_THREAD_RING_BUFFER_READ_SOURCE
|
||
#define HGL_THREAD_RING_BUFFER_READ_SOURCE
|
||
#include<string.h>
|
||
|
||
namespace hgl
|
||
{
|
||
/**
|
||
* 安全取得可读取数据长度
|
||
*/
|
||
template<typename T>
|
||
int RingBuffer<T>::SafeGetReadSize()
|
||
{
|
||
Lock();
|
||
|
||
const int result=_GetReadSize();
|
||
|
||
Unlock();
|
||
|
||
return(result);
|
||
}
|
||
|
||
/**
|
||
* 安全尝试取得可读取数据长度
|
||
*/
|
||
template<typename T>
|
||
bool RingBuffer<T>::SafeTryGetReadSize(int &result)
|
||
{
|
||
if(!TryLock())
|
||
return(false);
|
||
|
||
result=_GetReadSize();
|
||
|
||
Unlock();
|
||
|
||
return(true);
|
||
}
|
||
|
||
template<typename T>
|
||
int RingBuffer<T>::ReadStart(bool peek)
|
||
{
|
||
ClampPosition();
|
||
|
||
write_off=write_pos%buffer_size;
|
||
|
||
read_max=_GetReadSize();
|
||
|
||
read_peek=peek; //标记是否真的取走
|
||
read_count=0;
|
||
read_cur=read_pos;
|
||
|
||
return(read_max);
|
||
}
|
||
|
||
template<typename T>
|
||
int RingBuffer<T>::_SafeReadStart(bool peek)
|
||
{
|
||
ReadStart(peek);
|
||
|
||
if(read_max<=0)
|
||
Unlock();
|
||
|
||
return(read_max);
|
||
}
|
||
|
||
/**
|
||
* 尝试开始读取数据,如失败或没有数据会立即解锁,不必再次调用SafeReadEnd
|
||
* @param peek 是否真的取出数据
|
||
* @return >0 可供读取的数据数量
|
||
* @return =0 没有可供读取的数据
|
||
* @return <0 暂时不能读取
|
||
*/
|
||
template<typename T>
|
||
int RingBuffer<T>::SafeTryReadStart(bool peek)
|
||
{
|
||
if(!TryLock())
|
||
return(-1);
|
||
|
||
return _SafeReadStart(peek);
|
||
}
|
||
|
||
/**
|
||
* 开始读取数据,如果没有数据会立即关闭缓冲区,不必再次调用SafeReadEnd
|
||
* @param peek 是否真的取出数据
|
||
* @return 可供读取的数据数量
|
||
*/
|
||
template<typename T>
|
||
int RingBuffer<T>::SafeReadStart(bool peek)
|
||
{
|
||
Lock();
|
||
|
||
return _SafeReadStart(peek);
|
||
}
|
||
|
||
/**
|
||
* 读取数据
|
||
* @param data 欲将访问数据存放的内存地址,可为NULL用于单纯后移读取指针
|
||
* @param size 欲访问的数据长度
|
||
* @param peek 是否后移访问指针(默认为真,仅针对当前这一次)
|
||
* @return 实际可访问的数据长度
|
||
*/
|
||
template<typename T>
|
||
int RingBuffer<T>::Read(T *data,int size,bool peek)
|
||
{
|
||
if(size<=0)return(-1);
|
||
|
||
const int result=_Read(data,size,peek);
|
||
|
||
if(peek)
|
||
read_count+=result;
|
||
|
||
return(result);
|
||
}
|
||
|
||
/**
|
||
* 读取结束
|
||
* @return 返回读取的数据长度
|
||
*/
|
||
template<typename T>
|
||
int RingBuffer<T>::ReadEnd()
|
||
{
|
||
const int result=read_count;
|
||
|
||
if(read_peek&&result)
|
||
read_pos=read_cur;
|
||
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 安全读取结束
|
||
* @return 返回读取的数据长度
|
||
*/
|
||
template<typename T>
|
||
int RingBuffer<T>::SafeReadEnd()
|
||
{
|
||
const int result=ReadEnd();
|
||
|
||
Unlock();
|
||
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 安全的读取数据,,此函数会直接开锁解锁,用于少量的一次性处理。如大量的数据要分次读取,请使用SafeReadStart/SafeReadEnd
|
||
* @param data 欲将访问数据存放的内存地址,可为NULL用于单纯后移读取指针
|
||
* @param size 欲访问的数据长度
|
||
* @param peek 是否真的取出数据
|
||
* @return 实际读取的数据长度
|
||
* @return -1 出错
|
||
*/
|
||
template<typename T>
|
||
int RingBuffer<T>::SafeRead(T *data,int size,bool peek)
|
||
{
|
||
if(size<0)return(-1);
|
||
if(size&&!data)return(-1);
|
||
|
||
if(SafeReadStart(peek)<=0)
|
||
return(-1);
|
||
|
||
Read(data,size,peek);
|
||
|
||
return SafeReadEnd();
|
||
}
|
||
|
||
template<typename T>
|
||
int RingBuffer<T>::_Read(T *data,int size,bool peek)
|
||
{
|
||
if(size<=0||read_max<=0)return(0);
|
||
|
||
if(size>read_max)
|
||
size=read_max;
|
||
|
||
if(size>0)
|
||
{
|
||
if(data) //data可以为空,用于先尝试取数据后直接移走
|
||
{
|
||
const int temp_read =read_cur %buffer_size;
|
||
|
||
if(temp_read<write_off)
|
||
{
|
||
memcpy(data,buffer+temp_read,size*sizeof(T));
|
||
}
|
||
else
|
||
{
|
||
int temp=buffer_size-temp_read;
|
||
|
||
if(size>temp)
|
||
{
|
||
memcpy(data,buffer+temp_read,temp*sizeof(T));
|
||
|
||
memcpy((char *)(data+temp),buffer,(size-temp)*sizeof(T));
|
||
}
|
||
else
|
||
{
|
||
memcpy(data,buffer+temp_read,size*sizeof(T));
|
||
}
|
||
}
|
||
}//if(data)
|
||
|
||
if(peek)
|
||
{
|
||
read_cur+=size;
|
||
read_max-=size;
|
||
}
|
||
}
|
||
|
||
return(size);
|
||
}
|
||
}//namespace hgl
|
||
#endif//HGL_THREAD_RING_BUFFER_READ_SOURCE
|