找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 7995|回复: 1

抽丝剥茧,ACE_Message_Block 的尺寸辨析(1)

[复制链接]
发表于 2007-12-26 22:36:03 | 显示全部楼层 |阅读模式
Winston原创,ACE开发者论坛版权所有。[url=http://www.acejoy.com/]www.acejoy.com[/url]

ACE_Message_Block是ACE系统里面的“黏合剂”,所有的数据处理都涉及到ACE_Message_Block的使用。所以,有效的用好这个类很重要。
       开发过程中,对这个类的使用,经常碰见的问题就是:居然有多个尺寸的表达方式,而且文档描述不清,比较容易造成混乱和误用。这里做一下解析,让大家明白用法上的差别。
1、length()和length(size_t len)。实现代码如下:
──────────────────────────────
  1. ACE_INLINE size_t
  2. ACE_Message_Block::length (void) const
  3. {
  4.   ACE_TRACE ("ACE_Message_Block::length");
  5.   return this->wr_ptr_ - this->rd_ptr_;
  6. }
  7. // Sets the length of the "active" portion of the message.  This is
  8. // defined as the offset from RD_PTR to WR_PTR.
  9. ACE_INLINE void
  10. ACE_Message_Block::length (size_t len)
  11. {
  12.   ACE_TRACE ("ACE_Message_Block::length");
  13.   this->wr_ptr_ = this->rd_ptr_ + len;
  14. }
复制代码
可以清楚的看出,这个方法在取值的时候,是用“写指针” ─  “读指针”,
而设置的时候,是把“写指针”置为“读指针”+ 长度。
所以设置的时候请注意,不要产生越界行为。
──────────────────────────────
2、total_length()
──────────────────────────────
  1. size_t
  2. ACE_Message_Block::total_length (void) const
  3. {
  4.   ACE_TRACE ("ACE_Message_Block::total_length");
  5.   size_t length = 0;
  6.   for (const ACE_Message_Block *i = this;
  7.        i != 0;
  8.        i = i->cont ())
  9.     length += i->length ();
  10.   return length;
  11. }
复制代码
ACE_Message_Block有个重要的概念,是可以实现为内部单链表,外部双链表。
内部单链表可以用于支持复合消息,如消息头+消息尾,也可用于层次化协议栈。cont()方法就是用于此用途。
total_length()这个方法是返回每一个内部单链表中所有被链接的消息块长度之和。
3、size()和size(size_t length)
──────────────────────────────
  1. // Return the length of the potential size of the message.
  2. ACE_INLINE size_t
  3. ACE_Message_Block::size (void) const
  4. {
  5.   ACE_TRACE ("ACE_Message_Block::size");
  6.   return this->data_block ()->size ();
  7. }
  8. int
  9. ACE_Message_Block::size (size_t length)
  10. {
  11.   ACE_TRACE ("ACE_Message_Block::size");
  12.   // Resize the underlying <ACE_Data_Block>.
  13.   if (this->data_block ()->size (length) == -1)
  14.     return -1;
  15.   return 0;
  16. }
  17. 这两个方法,操作的是ACE_Message_Block底层的ACE_Data_Block 对象的方法:
  18. ACE_INLINE size_t
  19. ACE_Data_Block::size (void) const
  20. {
  21.   ACE_TRACE ("ACE_Data_Block::size");
  22.   return this->cur_size_;
  23. }
  24. int
  25. ACE_Data_Block::size (size_t length)
  26. {
  27.   ACE_TRACE ("ACE_Data_Block::size");
  28.   if (length <= this->max_size_)
  29.     this->cur_size_ = length;
  30.   else
  31.     {
  32.       // We need to resize!
  33.       char *buf = 0;
  34.       ACE_ALLOCATOR_RETURN (buf,
  35.                             (char *) this->allocator_strategy_->malloc (length),
  36.                             -1);
  37.       ACE_OS::memcpy (buf,
  38.                       this->base_,
  39.                       this->cur_size_);
  40.       if (ACE_BIT_DISABLED (this->flags_,
  41.                             ACE_Message_Block::DONT_DELETE))
  42.         this->allocator_strategy_->free ((void *) this->base_);
  43.       else
  44.         // We now assume ownership.
  45.         ACE_CLR_BITS (this->flags_,
  46.                       ACE_Message_Block::DONT_DELETE);
  47.       this->max_size_ = length;
  48.       this->cur_size_ = length;
  49.       this->base_ = buf;
  50.     }
  51.   return 0;
  52. }
复制代码
从上面的代码可以看出,当是用size(size_t length)进行设置时,如果length大于当前已经拥有的尺寸,会导致内存重新分配,把已有数据重新复制到新内存地址。而是用size()返回时,是返回当前设置的数据区大小,与读写指针没有任何关系。
发表于 2014-5-31 21:58:47 | 显示全部楼层
下面没有了?
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-11-21 17:37 , Processed in 0.029207 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表