ACE_Message_Block

分类: cACE_Message_Block是ACE中一个很核心的基础类,应用非常广泛,所以需要花点心思去研究。学习的过程有几点心得体会记录下吧。

        创建消息的这四点引自http://hi.baidu.com/zoupng/blog/item/562290878b31c52ec75cc35c.html

1、直接给消息块分配内存空间创建。

     ACE_Message_Block *mb = new ACE_Message_Block (30);

2、共享底层数据块创建。

    char buffer[100];

     ACE_Message_Block *mb = new ACE_Message_Block (buffer,30);

这种方式共享底层的数据块,被创建的消息块并不拷贝该数据,也不假定自己拥有它的所有权。在消息块mb被销毁时,相关联的数据缓冲区data将不会被销毁。这是有意义的:消息块没有拷贝数据,因此内存也不是它分配的,这样它也不应该负责销毁它。

3、通过duplicate()函数从已有的消息块中创建副本。

     ACE_Message_Block *mb = new ACE_Message_Block (30);

     ACE_Message_Block *mb2 = mb->duplicate();

这种方式下,mb2和mb共享同一数据空间,使用的是ACE_Message_Block的引用计数机制。它返回指向要被复制的消息块的指针,并在内部增加内部引用计数。

4、通过clone()函数从已有的消息块中复制。

     ACE_Message_Block *mb = new ACE_Message_Block (30);

     ACE_Message_Block *mb2 = mb->clone();

clone()方法实际地创建整个消息块的新副本,包括它的数据块和附加部分;也就是说,这是一次"深拷贝"。

(第五点引自http://blog.csdn.net/ydogg/archive/2007/10/10/1818949.aspx)

5、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时不考虑其它会导致指针悬空。

理解ACE_Message_Block是用ACE_Data_Block来保存数据的,这一点很关键。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ydogg/archive/2007/10/10/1818949.aspx 

补充点吧:

1、ACE_Message_Block的几个大小,让人头晕,下面这张图非常清晰地显示了它们的计算方法,如果使用wr_ptr往消息中写了数据,如果自己不挪动指针的话,length的大小是不会改变的,length的大小等于wr_ptr指针的位置减去rd_ptr的位置。

 ACE_Message_Block - 绚丽也尘埃 - 处女地

2、使用cont方法可以将消息简单地连接起来,比使用消息队列要简单。

给出一段示例代码吧,这里没有涉及消息的到期时间和执行之间等,这些特性需要结合动态队列来学习使用。

 ACE_Message_Block* mb = new ACE_Message_Block(30);

 ACE_DEBUG((LM_DEBUG, "capacity : %d, length : %d, space : %dn", mb->capacity(), mb->length(), mb->space()));

 //获得写指针
 char* ptr = mb->wr_ptr();

 //将数据写入消息中
 ACE_OS::memcpy(ptr, "fzjfzjfzj", 3);

 //挪动写指针
 mb->wr_ptr(9);

 //测试下引用计数,duplicate是浅拷贝,这样mb2和mb就指向同一个消息了
 ACE_Message_Block *mb2 = mb->duplicate();

 //clone是深度拷贝,不会增加引用计数
 ACE_Message_Block *mb3 = mb->clone();

 //释放下试试
 //mb2->release();

 //将读指针往前挪动四个位置会导致length=5
 //mb->rd_ptr(4);

 ACE_DEBUG((LM_DEBUG, "capacity : %d, length : %d, space : %d, reference_count : %dn", mb->capacity(), mb->length(), mb->space(),  mb->reference_count()));

 //再构造一个消息,用于和mb串联起来
 ACE_Message_Block* mb4 = new ACE_Message_Block(30);

 ptr = mb4->wr_ptr();

 ACE_OS::memcpy(ptr, "wxy", 3);

 //将mb和mb4串联起来
 mb->cont(mb4);

 //我期待这样导致循环链表,结果是程序卡死不动了,这里需要分析下cont的源代码
 //mb4->cont(mb);

 ACE_Message_Block* pMessageBlock = mb;

 //遍历消息
 for(; pMessageBlock != NULL; pMessageBlock = mb->cont())
 {
  //注意这个total_capacity的值哦
  ACE_DEBUG((LM_DEBUG, "data: %s, total_length: %dn", pMessageBlock->rd_ptr(), pMessageBlock->total_capacity()));
  mb = pMessageBlock;
 }

 //在栈中构造一个消息,调用其release方法会导致断言失败
 //这是因为使用delete释放栈空间
 //ACE_Message_Block mb5 (30);

 //ptr = mb5.wr_ptr();

 //ACE_OS::memcpy(ptr, "wyy", 3);

 //mb5.release();

 

//使用copy的时候需要注意每次copy之后会在字符串后面添加一个''

//下面的例子会存入"helloworld"

ACE_Message_Block mb6 (30);

mb6.copy("hello");

mb6.copy("world");

//如果这样做的话就只会hello了

//mb6.copy("helloworld");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值