龙仪的家

导航

<2006年5月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

随笔分类

文章分类

收藏夹

随笔档案

文章档案

统计

我的常用网址

代码库之十-循环缓冲类(0.1)

缓冲管理是个重要而且麻烦的问题,频繁的new绝对不是好事,现在不是提倡节约型社会嘛,咱们也来节约一下,好了废话少说。这个缓冲是个循环缓冲的封装,就是循环利用已有的缓冲区,当然前提是你得申请的足够大。
感谢朋友们的支持,由于这个类是从我的以前的工程中移植过来的,所以很多实现不符合标准,见谅,但我会努力完善的,谢谢你们的支持。拷贝和赋值已经禁止,异常处理已经加上,另外对于hpho的话我不是很理解,其实这个类正如其名,是循环缓冲类,大概用途就是在数据不完整,或者在多线程处理缓冲中使用的,比如一个线程产生数据,不断加入到这个缓冲区,另一个线程不断取得数据,目的就是提供一个临时存放的缓冲,而不用频繁new新的缓冲。由于这个类是循环的,所以外部直接利用缓冲内存指针,只会让外部使用比较麻烦。另外对于不在构造中使用new是我的一个理解,因为如果在构造中new出异常,这个对象是不会析构的。大家的支持是我的动力!
/////////////////////////////////////////////H//////////////////////////////////////////////////////////////////////

#ifndef LGLIB_LOOPBUFFER_H
#define LGLIB_LOOPBUFFER_H

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "lg_MultiEvent.h"

namespace lglib
{
 //循环缓冲类 这个类利用循环放置数据的方法节省了一些系统开销
 //注意这是个线性缓冲,如果用于多线程需要进行一些处理

 //time: 2006-4-26

 class __LGLIB__ lg_LoopBuffer 
 {
 public:
  lg_LoopBuffer(); //默认构造

  virtual ~lg_LoopBuffer();
  void InitBuffer(uint32 dwOriginSize);
  void ResetBuffer();
  //写入数据
  int32 WriteBuffer(uint8* buf,uint32 len);
  //读出数据
  int32 GetBuffer(uint8* buf,uint32 len);
  //取得缓冲区剩余数据大小
  uint32 GetCountNeedProcess();
  
 private:
//禁止构造或者其他赋值操作比较操作,还是不定义实现比较好,安全第一 : )
  lg_LoopBuffer(const lg_LoopBuffer& ); //禁止拷贝构造
  lg_LoopBuffer& operator= (const lg_LoopBuffer& ); //禁止赋值
  bool operator= =(const lg_LoopBuffer& ); //禁止比较
//.....................
  inline uint32 GetPosition(uint64 pos);
 private:
  uint8 * m_pLoopBuffer;
  uint64 m_dwWritePos;
  uint64 m_dwReadPos;
  uint32 m_dwMaxBuffersize;
 };
}
#endif
//////////////////////////////////////////////CPP////////////////////////////////////////////////////
#include "stdafx.h"
#include "lg_LoopBuffer.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
namespace lglib
{


  lg_LoopBuffer::lg_LoopBuffer()
 : m_pLoopBuffer(NULL) , m_dwWritePos(0) ,
 m_dwReadPos(0) , m_dwMaxBuffersize(0)
 {

 }

 lg_LoopBuffer::~lg_LoopBuffer()
 {
  if(m_pLoopBuffer){
   delete [] m_pLoopBuffer;
   m_pLoopBuffer = NULL;
  }
 }
 //初始化数据
 void lg_LoopBuffer::InitBuffer(uint32 dwOriginSize)
 {
  //其实单线程这里可以删掉缓冲,再重新初始化,但由于担心在多线程会出问题所以没有这么做
  if(NULL != m_pLoopBuffer){
   throw lg_Exception("lg_LoopBuffer::InitBuffer","缓冲区已经存在",2);
  }

  m_dwMaxBuffersize = dwOriginSize;
  m_pLoopBuffer = new uint8[m_dwMaxBuffersize];
 }

 //重置缓冲区,然后可以再利用
 void lg_LoopBuffer::ResetBuffer()
 {
  if(NULL == m_pLoopBuffer)
   throw lg_Exception("lg_LoopBuffer::ResetBuffer","缓冲区没有初始化",3);
  m_dwWritePos = 0;
  m_dwReadPos = 0;
 }
 
 //取得当前的位置,由于这个函数是private所以就不加异常处理了
 inline uint32 lg_LoopBuffer::GetPosition(uint64 pos)
 {
    return static_cast<uint32>(pos%m_dwMaxBuffersize);
 }

 //写入数据
 int lg_LoopBuffer::WriteBuffer(uint8* buf,uint32 len)
 {
  if(NULL == m_pLoopBuffer)
   throw lg_Exception("lg_LoopBuffer::WriteBuffer","缓冲区没有初始化",4);

  //检测输入有效性
  if(len>0&&len<=m_dwMaxBuffersize){
   
   if(((m_dwMaxBuffersize + m_dwReadPos) >= (m_dwWritePos + len))
    ||(m_dwWritePos == 0&&m_dwReadPos == 0)){

    uint32 pos = GetPosition(m_dwWritePos);
    uint32 distance = m_dwMaxBuffersize - pos;

    if(distance >= len){
     memcpy(&m_pLoopBuffer[pos],buf,len);
    }else{
     memcpy(&m_pLoopBuffer[pos],buf,distance);
     memcpy(m_pLoopBuffer,&buf[distance],len-distance);
    }

    m_dwWritePos+=len;

    return len;
   }
  }
  return -1;
 }

 //读出数据
 int32 lg_LoopBuffer::GetBuffer(uint8* buf,uint32 len)
 {
  if(NULL == m_pLoopBuffer)
   throw lg_Exception("lg_LoopBuffer::GetBuffer","缓冲区没有初始化",5);

  if(m_dwWritePos < (m_dwReadPos + len)) return 0;

  uint32 pos = GetPosition(m_dwReadPos);

  uint32 distance = m_dwMaxBuffersize - pos;
  if(distance >= len){
   memcpy(buf,&m_pLoopBuffer[pos],len);
  }else{
   memcpy(buf,&m_pLoopBuffer[pos],distance);
   memcpy(&buf[distance],m_pLoopBuffer,len-distance);
  }

  m_dwReadPos += len;

  return len;
 }

 //取得缓冲区剩余数据大小
 uint32 lg_LoopBuffer::GetCountNeedProcess()
 {
  if(NULL == m_pLoopBuffer)
   throw lg_Exception("lg_LoopBuffer::GetCountNeedProcess","缓冲区没有初始化",6);

  return static_cast<uint32>(m_dwWritePos - m_dwReadPos);
 }

}

posted on 2006-05-05 11:21 龙仪 阅读(1846) 评论(4)  编辑 收藏

评论

# re: 代码库之十-循环缓冲类 2006-05-05 20:47 hpho

1, 拷贝和赋值行为没被禁止或重写.
2, 内部状态不一至, 即调用WriteBuffer()先没调用InitBuffer(), 没有任何异常, 这里的m_dwMaxBuffersize也没被合理初始化.
3, "不在构造函数中使用new是个好习惯"不知有什么理据说明这个命题?
4, 既然此类的数据来源于(WriteBuffer())里的 buf, 那为何我还要把它复制到此类去呢?直接用这个BUF的内存就行了么. 最大问题是这个类的内存是不能直接访问的, 要使用还要在NEW一个块BUF来把类里的数据复制(GetBuffer())过去然后使用. 那"减少频繁的new"好像体现不出来.
 

# re: 代码库之十-循环缓冲类(0.1) 2006-05-06 14:08 hpho

哦, 原来是这样用的呀, 偶笨笨一开始没看懂. 作为缓冲我觉应该是唯一的, 即把拷贝和赋值都禁了比较好吧:-P 
还有两点拙见:
1,就是把线程部分分离出来, 就是线程和缓冲相互独立可以分开也可以叠加使用.
2,这里m_pLoopBuffer的new和delete最好是可配置的.意思是说可以用API如GlobalAlloc等系统相关的内存分配函数.因为可能有特殊内存空间的需求.

# re: 代码库之十-循环缓冲类(0.1) 2006-05-06 15:20 龙仪

事件部分已经分离,有需要的可以自行加上,至于new和delete的配置为了保持代码的简洁,这次没有加上,如果自己需要完全可以定义几个宏,利用不同的宏来条件编译,或者采用加参数的方式,有兴趣的读者也可以把代码贴上来,大家一同鉴赏。: - P

# re: 代码库之十-循环缓冲类(0.1) 2006-05-08 14:11 清风雨

没有细看代码,根据你的目的,为何不用STL的容器呢?至少STLport的实现满足你的需求。

标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]