Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1020919
  • 博文数量: 326
  • 博客积分: 10135
  • 博客等级: 上将
  • 技术积分: 2490
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-22 23:53
文章分类

全部博文(326)

文章存档

2014年(1)

2012年(4)

2011年(1)

2010年(4)

2009年(41)

2008年(44)

2007年(63)

2006年(168)

我的朋友

分类:

2007-02-12 10:24:56

http://blog.csdn.net/btooth/

CBufBase类规定了动态缓存的接口标准,在内存中存储缓冲数据,可以动态的扩展和收缩。CBase是CBufBase的父类,它使所有从他 派生的类都在heap(堆)上初始化。CBufBase类的成员函数可以归为以下几类:

基本函数包括:

<1> InsertL(), Read(), Write(), Delete(), Reset() 和 Size();这些函数的可以和内存的其他部分进行数据交换,并且可以删除数据.
<2> ExpandL() 和 Resize() 函数使其他的一些操作在性能上得到提升
<3> Compress() 函数清理释放那些已经分配但没有使用的内存碎片。
<4> Ptr() 和 BackPtr() 函数用于从个一个指定的位置向前或者向后查找临近的数据。

另外很多重要数据都保存在数据成员中。

这里有两种比较重要的缓冲类型,他们都是从CBufBase派生而来的,分别是CBufFlat(平面缓冲)和CBufSeg(分段缓冲)。

下面介绍一些缓冲类型的基本使用方法。

[1] CBufSeg 的 NewL()方法

static CBufSeg* NewL(TInt anExpandSize);

分配和构造一个分段缓冲,如果当前没有足够的内存,那么就异常退出(leave)。

参数:
TInt anExpandSize
缓存的粒度:每一个段都包括了这个数值所指定的数据字节数。

例如:
CBufBase* Cbf=CBufSeg::NewL(10);
CleanupStack::PushL(Cbf);

[2] CBufFlat 的 NewL() 方法

static CBufFlat* NewL(TInt anExpandSize);

这个函数分配和构造一个平面缓冲。

如果当前没有足够的空间可分配,则发生leave。

TInt anExpandSize:指定缓冲扩展的粒度。当平面缓冲需要更多的空间时,那么分配所获得的内存是这个参数的整数倍。

这个函数返回一个指向缓冲的指针。

[3] CBufBase类InsertL()方法

InsertL()方法包括三个版本:

void InsertL(TInt aPos,const TDesC8& aDes);
void InsertL(TInt aPos,const TDesC8& aDes,TInt aLength);
void InsertL(TInt aPos,const TAny* aPtr,TInt aLength);

这个函数的作用是把数据插入到缓冲中,有三个版本的重载函数,在插入位上或在插入位后的数据被后移插入数据的长度,在插入位前的数据则保持原来的位置不动。需要注意的是,插入操作可能要求分配更多的内存。

在平面缓冲(CBufFlat)中,缓冲从它堆单元的ReAllocL()扩展,ReAllocL()在RHeap类中定义,根据指定数据的大小增加或者减少堆单元的尺寸。如果内存重新分配失败,那么插入操作也就失败,并且发生Leave.

在分段(segmented)缓冲中,内存的重新分配将被执行,哪怕要插入位置所在的段没有足够的空间,并且最近相邻的段也不可以用来包含新的数据,问题在于,只要有足够的新的段存在那么要插入的数据所需要的内存就可以被分配。每一个新段的长度就是缓冲粒度。如果扩展或者重新分配发生失败,那么函数异常退出。

插入操作也可能需要拖动数据,如果是平面缓冲,在插入点后面的数据将被拖动,以便产生一个裂口,这样新的数据就可以被放到 这个裂口中。如果是分段缓冲,并且这个缓冲刚刚建立,那么这种数据拖动是最小的,而且如果可能他拖动的也仅仅只是最近相邻的缓冲。这样做很有可能产生一些空间的浪费,但是对于大量数据的插入操作,分段缓冲在时间上是相当高效的。

参数:

TInt aPos:缓冲中将要插入数据的位置,这个值必须在缓冲大小的范围之内。

const TDesC8& aDes:指定要插入的数据,同时也指定了要插入数据的长度,其默认长度就是当前正在插入数据的长度,如果插入的长度已经被指定,那么默认长度就会被覆盖;

TInt aLength:指定插入数据的长度;

const TAny* aPtr:指定插入数据的地址;

如果插入请求的数据量超出了缓冲范围,并且请求空间更多空间时发生失败,那么函数异常推退出。


可以想象,平面缓冲是一个连续的内存空间,而分段缓冲则是把各个段分散在内存的各处,而在逻辑上则是一个整体。这样对于平面缓冲来说,它有较高的访问速度,但是内存却不易分配,更不易扩展。而分段缓冲则可以经常进行扩展或者收缩、插入删除等操作,但是访问效率可能要比平面缓冲略低一点。

如果对象有一个较长的生命期,或者程序在运行过程中有不可预知的成员插入,或者有与性能相关的对于大缓存的删除和插入操作 ,那么就应该考虑使用CBufSeg类。特别是那些经常改变缓存大小、频繁的进行删除和插入操作的程序,更加有必要考虑使用分段动态缓冲。

CBufSeg类实现了 CBufBase 抽象缓存接口,并且使用堆单元的双向链表来组织数据。每一个堆单元包含了缓存的一个段。可以这样认堆单元和段基本在概念上基本等同,只是堆单元从物理上描述,段则从逻辑上进行描述。在数据成员中包括了一个双向链表的锚点和最后操作的缓存位置的引用。这个引用表现的像cache(高速缓冲存储器),如果下一个操作使用一个相似的缓冲位置 那么指针指向运算的结果将会响应的更快。

[4] CBufSeg 类的 Ptr() 函数

virtual TPtr8 Ptr(TInt aPos);

返回一个TPtr8指针描述符,指向指定字节处到段结束处的段数据。指针获取的计算速度取决于缓冲中段的数量、以及当前指针和目标指针的距离。

以上是分段缓冲和平面缓冲的基本介绍;具体细节请参看SDK Help.

阅读(1006) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~