ACE_Message_Block消息数据类

  ACE_Message_Block

  ACE_Message_Block用于构建“固定”和“可变”长度的消息。ACE_Message_Block可以将多条消息连接在一起,形成一个链表,从而支持复合消息。ACE_Message_Block内部结构图如下:

1:ACE_Message_Block初始化与释放

  初始化一般用以下操作实现:

ACE_NEW_NORETURN (m_pRcvmb,ACE_Message_Block (1024));

ACE_Message_Block* p = new ACE_Message_Block(1024);

  这两种方式都可以实现ACE_Message_Block的new操作。ACE定义了一组申请内存的宏,内部都实现了new操作符。这组宏定义在如下:

#  if defined (ACE_HAS_NEW_NOTHROW)
#    define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL)    do { POINTER = new (ACE_nothrow) CONSTRUCTOR;      if (POINTER == 0) { errno = ENOMEM; return RET_VAL; }    } while (0)
#    define ACE_NEW(POINTER,CONSTRUCTOR)    do { POINTER = new(ACE_nothrow) CONSTRUCTOR;      if (POINTER == 0) { errno = ENOMEM; return; }    } while (0)
#    define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR)    do { POINTER = new(ACE_nothrow) CONSTRUCTOR;      if (POINTER == 0) { errno = ENOMEM; }    } while (0)

#  else

#    define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL)    do { try { POINTER = new CONSTRUCTOR; }      catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = 0; return RET_VAL; }    } while (0)

#    define ACE_NEW(POINTER,CONSTRUCTOR)    do { try { POINTER = new CONSTRUCTOR; }      catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = 0; return; }    } while (0)

#    define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR)    do { try { POINTER = new CONSTRUCTOR; }      catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = 0; }    } while (0)
#  endif /* ACE_HAS_NEW_NOTHROW */

  值得注意的是,ACE_Message_Block有多个构造函数,最常用的一个构造函数定义为:

  ACE_Message_Block (size_t size,
                     ACE_Message_Type type = MB_DATA,
                     ACE_Message_Block *cont = 0,
                     const char *data = 0,
                     ACE_Allocator *allocator_strategy = 0,
                     ACE_Lock *locking_strategy = 0,
                     unsigned long priority = ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY,
                     const ACE_Time_Value &execution_time = ACE_Time_Value::zero,
                     const ACE_Time_Value &deadline_time = ACE_Time_Value::max_time,
                     ACE_Allocator *data_block_allocator = 0,
                     ACE_Allocator *message_block_allocator = 0);

  在该构造函数内部,ACE_Message_Block调用了init_i函数,init_i内部调用了ACE_Data_Block的构造函数。ACE_Data_Block定义了一个char* base_ 指针,其构造函数会调用C风格的malloc方法为base_申请大小为size的空间。也就是说,ACE_Message_Block真正的数据载体是ACE_Data_Block。其实现代码为:

//ACE_Message_Block内部申请ACE_Data_Block的空间
ACE_NEW_MALLOC_RETURN (db,static_cast<ACE_Data_Block *> (data_block_allocator->malloc (sizeof (ACE_Data_Block))),
                             ACE_Data_Block (size,
                                             msg_type,
                                             msg_data,
                                             allocator_strategy,
                                             locking_strategy,
                                             flags,
                                             data_block_allocator),-1);

//ACE_Data_Block内部为base_申请大小为size的空间
if (msg_data == 0)
    {
      ACE_ALLOCATOR (this->base_,(char *) this->allocator_strategy_->malloc (size));
#if defined (ACE_INITIALIZE_MEMORY_BEFORE_USE)
      (void) ACE_OS::memset (this->base_,‘\0‘,size);
#endif /* ACE_INITIALIZE_MEMORY_BEFORE_USE */
    }

  释放ACE_Message_Block,调用release方法即可。release方法会将消息的引用计数减1,如果消息的引用计数为0,则释放该消息。

2:ACE_Message_Block写入数据  

  ACE_Message_Block内部有读地址和写地址,ACE_Message_Block的长度是写地址减去读地址的值。其定义为:

//读写地址
  /// Pointer to beginning of next read.
  size_t rd_ptr_;
  /// Pointer to beginning of next write.
  size_t wr_ptr_;

//长度
ACE_Message_Block::length (void) const
{
  ACE_TRACE ("ACE_Message_Block::length");
  return this->wr_ptr_ - this->rd_ptr_;
}

  rd_ptr()和wr_ptr()分别用于设置和获取读写地址的值。

  将buffer中的数据复制到ACE_Message_Block中,需要调用copy函数。copy函数内部用memcpy实现,将buf的size个BYTE拷贝到以wr_ptr_地址为首的地址上,并将wr_ptr_的值加上size,其实现为:

int ACE_Message_Block::copy (const char *buf, size_t n)
{
  ACE_TRACE ("ACE_Message_Block::copy");
  /*size_t len = static_cast<size_t> (this->end () - this->wr_ptr ());*/
  // Note that for this to work correct, end () *must* be >= mark ().
  size_t len = this->space ();
  if (len < n)
    {
      errno = ENOSPC;
      return -1;
    }
  else
    {
      (void) ACE_OS::memcpy (this->wr_ptr (),buf,n);
      this->wr_ptr (n);
      return 0;
    }
}

3:ACE_Message_Block复制操作

  ACE_Message_Block提供了clone和duplicate两个操作,clone是深复制,duplicate是浅复制,仅为消息的引用计数加1。

4:ACE_Message_Block消息链

  ACE_Message_Block内部定义3个指针:

/// Pointer to next message block in the chain.
  ACE_Message_Block *cont_;
  /// Pointer to next message in the list.
  ACE_Message_Block *next_;
  /// Pointer to previous message in the list.
  ACE_Message_Block *prev_;

  分别用重载函数cont()、next()、prev()来设置和获取邻居消息。其中,cont用于将复合消息连接在一起,next和prev用于连接消息链上的简单消息。

  一个消息链的示例如下:

#include "ace/OS.h"
#include "ace/Message_Block.h"

int main (int argc, char *argv[])
{
  ACE_Message_Block *head = new ACE_Message_Block (BUFSIZ);
  ACE_Message_Block *mblk = head;

  for (;;) {
    ssize_t nbytes = ACE::read_n (ACE_STDIN,mblk->wr_ptr (),mblk->size () ) ;
    if (nbytes <=  0)
      break; // Break out at EOF or error.
    // Advance the write pointer to the end of the buffer.
    mblk->wr_ptr (nbytes);
    // Allocate message block and chain it at the end of list.
    mblk->cont (new ACE_Message_Block (BUFSIZ));
    mblk = mblk->cont ();
  }
  // Print the contents of the list to the standard output.
  for (mblk = head; mblk != 0; mblk = mblk->cont ())
    ACE::write_n (ACE_STDOUT, mblk->rd_ptr (), mblk->length ());
  head->release (); // This releases all the memory in the chain.
  return 0;
}

C++ Network Programming. Volume 1: Mastering Complexity with ACE and Patterns

时间: 2024-12-18 08:33:27

ACE_Message_Block消息数据类的相关文章

Scala 深入浅出实战经典 第93讲:Akka第一个案例动手实战开发消息实体类

构建map,reduce之间通讯的消息实体类. 了解wordcount原理. DT大数据梦工厂微信公众账号:DT_Spark. DT大数据梦工厂的微信公众号是DT_Spark,每天都会有大数据实战视频发布,请您持续学习. 王家林DT大数据梦工厂scala的所有视频.PPT和代码在百度云盘的链接:http://pan.baidu.com/share/home?uk=4013289088#category/type=0&qq-pf-to=pcqq.group QQ群: DT大数据梦工厂① :4629

微信公众号发送消息之发送客服消息基类封装

当用户主动发消息给公众号的时候(包括发送信息.点击自定义菜单.订阅事件.扫描二维码事件.支付成功事件.用户维权),微信将会把消息数据推送给开发者,开发者在一段时间内(目前修改为48小时)可以调用客服消息接口,通过POST一个JSON数据包来发送消息给普通用户,在48小时内不限制发送次数.此接口主要用于客服等有人工消息处理环节的功能,方便开发者为用户提供更加优质的服务. http请求方式: POST https://api.weixin.qq.com/cgi-bin/message/custom/

微信公共平台消息回复类

<?php/** * 微信公共平台消息回复类 * * */class BBCweixin{  private $APPID="******"; private $APPSECRET="******"; /*  *文本消息回复  *@param array object  *@param string content  *@return string  */ public function resText($object,$content,$flag=0){  

Akka第一个案例动手实战开发消息实体类

学习了Akka第一个案例动手实战开发消息实体类,应用mapdata对单词级数,应用reduce对计数进行汇总,通过akka进行相互的消息通信. 代码案例如下: package akka.dt.app.messages; import java.util.List public class MapData{ privatie List<WordCount> dataList; public List<WordCount> getDataList()  {return dataList

【转】解决Maxwell发送Kafka消息数据倾斜问题

最近用Maxwell解析MySQL的Binlog,发送到Kafka进行处理,测试的时候发现一个问题,就是Kafka的Offset严重倾斜,三个partition,其中一个的offset已经快200万了,另外两个offset才不到两百.Kafka数据倾斜的问题一般是由于生产者使用的Partition接口实现类对分区处理的问题,一般是对key做hash之后,对分区数取模.当出现数据倾斜时,小量任务耗时远高于其它任务,从而使得整体耗时过大,未能充分发挥分布式系统的并行计算优势(参考Apache Kaf

MySql数据类型和Java数据类型对应一览

类型名称 显示长度 数据库类型 JAVA类型 JDBC类型索引(int) 描述             VARCHAR L+N VARCHAR java.lang.String 12   CHAR N CHAR java.lang.String 1   BLOB L+N BLOB java.lang.byte[] -4   TEXT 65535 VARCHAR java.lang.String -1               INTEGER 4 INTEGER UNSIGNED java.la

数据类与生成数据库表所需组成

Entityframework属于ORM框架,作用为:将数据类与数据库表关联起来. 数据类与生成数据库表所需组成: 普通类(实体类):定义了属性字段+限制 数据上下文类:继承了DbContext,(各实体类的集合).作用:生成数据库和操作数据库. 配置文件中.连接数据库的字符串.注意name必须与数据上下文类的派生类名称相同. 控制器中,数据库上下文类的实例化,然后使用给对象方可生成数据库.

数据类型和typeof操作符

虽然学习js有一段时间了,但是对js的基础语法却是有些生疏.最近在看jquery源码,决定随带总结一些基础的语法知识.今天总结一下数据类型和typeof,这在写js的时候,是不得不知道的知识. 数据类型: js有5中基本的数据类型:undefined,Null,Boolean,Number,string;有一种复杂的数据类型:object,js不支持所有自定义的数据类型,所以所有变量的值都是以上类型. typeof:它的出现用来检测变量的数据类型,它可能的值有6种. undefined---如果

mysql的char数据类型和varchar数据类型的选择

mysql的char数据类型和varchar数据类型的选择 存储引擎对于选择char和varchar的影响: 对于MyISAM存储引擎:最好使用固定长度的数据列代替可变长度的数据列.这样可以使整个表静态化,从而使数据检索更快,用空间换时间 对于InnoDB存储引擎:使用可变长度的数据列,因为InnoDB数据表的存储格式不分固定长度和可变长度,因此使用char不一定比使用 varchar更好,但由于varchar是按照实际的长度存储,比较节省空间,所以对磁盘I/O和数据存储总量比较好 mysql并