ACE_Message_Block

来源:互联网 发布:台湾旅游业 知乎 编辑:程序博客网 时间:2024/06/05 18:34

ACE_Message_Block中有多个获取大小或者长度的函数,容易混淆.
下图是根据ACE_Message_Block(实际是ACE_Data_Block)空间的处理状况所绘,能比较清晰的反应出它们的异同.
需要注意,为了表现出多样性,下图是wr_ptr(),rd_ptr(),size()都调用过之后的情景.


 红色表示是ACE_Message_Block独有的函数, 其余则ACE_Message_BlockACE_Data_Block均有.
矩形纸上函数的返回值均为指针类型,之下的返回值均为size_t类型.
 

函数

说明

length()

有效数据的长度

== wr_ptr() – rd_ptr()

size()

全部可用空间的长度,如果没有size()而变小,则等同capacity()

== mark() – base()

space()

剩余可用空间的长度

<= size() - length(),因为不含rd_ptr()移动过的空间

== mark() – wr_ptr()

capacity()

最大空间的长度(ACE_Message_Block构造或初始化时所用参数值)

== end() – base()

total_length()

复合消息(ACE_Message_Block内单向链 cont())的总长度

total_size()

复合消息(ACE_Message_Block内单向链 cont())的总大小

total_capacity()

复合消息(ACE_Message_Block内单向链 cont())的总空间大小

  duplicate()浅拷贝函数,公用一个内部的ACE_Data_Block
ACE_Message_Block::duplicate()
ACE_Data_Block.duplicate()的实现是不同的.
ACE_Data_Block::duplicate()
简单的只是将自身的reference+1, 然后返回自身(this)
ACE_Message_Block:duplicate()
则将自身copy了一份, 然后将自身的状态值赋给拷贝,注意它们公用同一个data_block.而且ACE_Message_Block::duplicate()支持复合消息,它会检查内部单向链,来依次调用其duplicate().

ACE_Message_Block::clone()深拷贝, 不但拷贝自身,内部的ACE_Data_Block也一并拷贝了,并且支持复合消息.

ACE_Data_Block.size(size_t len)函数, 动态的变化ACE_Data_Block持有的空间.
ACE_Message_Block.size(size_t len)
函数是ACE_Data_Block.size(size_t len)的简单包裹.
如果len比现有的尺寸小, 简单的cur_size_ = length;
如果len比现有的尺寸大, 会申请新的空间并拷贝原所有数据.

注意! 这里可能会发生空间控制权的转换! 即标志位DONT_DELETE的变化.若原ACE_Data_Block使用托管空间, 则此时会更替为自己申请的空间,从而拥有了控制权, 所以此时要注意原有空间的管理.
ACE_Message_BlockACE_Data_Block, 除非主动调用size(), 否则它们不会自动申请和扩大空间.

ACE_Message_Block::crunch() 将现有数据移动到现有的缓冲的开始.

ACE_Message_Block::reset()将现有读写指针赋为初始值(ACE_Data_Block.base())

ACE_Message_Block::base()是对ACE_Data_Block.base()的简单包裹

1)ACE_Message_Block的构造函数中,如果dataNULL, ACE_Message_Block会为其自动分配空间. 但如dataNULL,ACE_Message_Block会直接引用data指向的空间, 并不会进行新的空间分配和拷贝.

所以需要特别注意, ACE_Message_Block的实例没有销毁之前,不能释放data指向的空间.

 2)虽然ACE_Message_Block会根据size的值来更改自己的size(),wr_ptr不会根据data的长度进行设置, 造成length()的返回为0.

需要特别注意, 当构造一个ACE_Message_Block实例后, 随之需要追加数据时,必须设置wr_ptr的值,否则原有数据将会被覆写.

 此时的含义是: ACE_Message_Block代管了data缓冲区,但不负责缓冲区的空间管理(因为也不是由它申请的).

 

默认定义的flag: enum  { DONT_DELETE = 01, USER_FLAGS = 0x1000 }

1) set_flags()clr_flags()是对ACE_Message_Block中的数据指针(ACE_Data_Block*)进行设置.

2) set_self_flags(),clr_self_flags()是对ACE_Message_Block本身进行设置.

ACE_Message_Block::copy(const char* buf函数将字符串copyACE_Message_Block, 如果内在空间不足, 将会返回-1.

需要特别注意, copy的数据将包括末尾的0, 也就是copy的数据长度为strlen(buf)+1.

而且, 会自动进行wr_ptr()的设置

 ACE_Data_Block的析构函数是释放持有空间base_的惟一路径(size()的情况不讨论).

ACE_Data_Block中通过duplicate()递增引用计数. ACE_Data_Block中通过release()递减引用计数, 当引用计数为0,先调用ACE_Data_Block析构函数,然后释放ACE_Data_Block自身.
注意, ACE_Data_Block的构造和析构函数都不知道引用计数的存在. 在构造函数中, 只是设置了初始值1.

 ACE_Data_Block一个很奇怪的地方就是ACE_Data_Block::duplicate()的实现, 并没有创建新的拷贝, 而仅仅是返回了自身(return this). 这中实现方式带来了很多奇怪的问题.如下面的2,3.
 release()-> release_no_delete()->release_i()->~ACE_Data_Block()

 如果在Stack上构造ACE_Data_Block,那么不能使用release()函数, 因为release()函数会试图删除this

 如果在stack上构造ACE_Data_Block, 那么不能使用duplicate()函数, 因为duplicate()返回的是this指针, 栈中的ACE_Data_Block析构后会导致问题.

 如果在heap上构造ACE_Data_Block,那么尽量使用release()来替代delete, 如果存在因为析构并不处理reference count, delete时不考虑其它会导致指针悬空.

原创粉丝点击