ACE_Message_Block消息数据类
ACE_Message_Block
ACE_Message_Block用于构建“固定”和“可变”长度的消息。ACE_Message_Block可以将多条消息连接在一起,形成一个链表,从而支持复合消息。ACE_Message_Block内部结构图如下:
头文件“Message_Block.h”。
1:ACE_Message_Block初始化与释放
初始化一般用以下操作实现:
ACE_NEW_NORETURN (m_pRcvmb,ACE_Message_Block ()); ACE_Message_Block* p = new ACE_Message_Block();
这两种方式都可以实现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 == ) { errno = ENOMEM; return RET_VAL; } \
} while ()
# define ACE_NEW(POINTER,CONSTRUCTOR) \
do { POINTER = new(ACE_nothrow) CONSTRUCTOR; \
if (POINTER == ) { errno = ENOMEM; return; } \
} while ()
# define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR) \
do { POINTER = new(ACE_nothrow) CONSTRUCTOR; \
if (POINTER == ) { errno = ENOMEM; } \
} while () # 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 = ; return RET_VAL; } \
} while () # define ACE_NEW(POINTER,CONSTRUCTOR) \
do { try { POINTER = new CONSTRUCTOR; } \
catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = ; return; } \
} while () # define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR) \
do { try { POINTER = new CONSTRUCTOR; } \
catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = ; } \
} while ()
# endif /* ACE_HAS_NEW_NOTHROW */
值得注意的是,ACE_Message_Block有多个构造函数,最常用的一个构造函数定义为:
ACE_Message_Block (size_t size,
ACE_Message_Type type = MB_DATA,
ACE_Message_Block *cont = ,
const char *data = ,
ACE_Allocator *allocator_strategy = ,
ACE_Lock *locking_strategy = ,
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 = ,
ACE_Allocator *message_block_allocator = );
在该构造函数内部,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),-); //ACE_Data_Block内部为base_申请大小为size的空间
if (msg_data == )
{
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 -;
}
else
{
(void) ACE_OS::memcpy (this->wr_ptr (),buf,n);
this->wr_ptr (n);
return ;
}
}
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 <= )
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 != ; mblk = mblk->cont ())
ACE::write_n (ACE_STDOUT, mblk->rd_ptr (), mblk->length ());
head->release (); // This releases all the memory in the chain.
return ;
}
5:size()、length()、space()、capacity()
一张图说明ACE_Message_Block这几个函数的含义:

length= wr_ptr - rd_ptr;
space = mark - wr_ptr;
size = mark - base;
capacity = end - base;
其中,capacity和size的关系参考stl的capacity和size。int size (size_t length)可以动态申请空间。
C++ Network Programming. Volume 1: Mastering Complexity with ACE and Patterns
ACE_Message_Block消息数据类的更多相关文章
- phpMemcache消息队列类
<?php /** * Memcache 消息队列类 */ class QMC { const PREFIX = 'ASDFASDFFWQKE'; /** * 初始化 mc * @staticv ...
- 【转】解决Maxwell发送Kafka消息数据倾斜问题
最近用Maxwell解析MySQL的Binlog,发送到Kafka进行处理,测试的时候发现一个问题,就是Kafka的Offset严重倾斜,三个partition,其中一个的offset已经快200万了 ...
- 代码的坏味道(16)——纯稚的数据类(Data Class)
坏味道--纯稚的数据类(Data Class) 特征 纯稚的数据类(Data Class) 指的是只包含字段和访问它们的getter和setter函数的类.这些仅仅是供其他类使用的数据容器.这些类不包 ...
- Java数据类型和MySql数据类型对应一览
类型名称 显示长度 数据库类型 JAVA类型 JDBC类型索引(int) 描述 VARCHAR L+N VARCHAR java.lang.String 12 CHAR N ...
- 数据类型和typeof操作符
虽然学习js有一段时间了,但是对js的基础语法却是有些生疏.最近在看jquery源码,决定随带总结一些基础的语法知识.今天总结一下数据类型和typeof,这在写js的时候,是不得不知道的知识. 数据类 ...
- Kafka consumer处理大消息数据问题
案例分析 处理kafka consumer的程序的时候,发现如下错误: ERROR [2016-07-22 07:16:02,466] com.flow.kafka.consumer.main.Kaf ...
- 如何创建一个要素数据类 IField,IFieldEdit,IFields,IFieldsEditI,GeometryDef,IGeometryDefEdit接口
如何创建一个要素数据类 创建要素类用到了IFeatureWorkspace.CreateFeatureClass方法,在这个方法中有众多的参数,为了满足这些参数,我们要学习和了解下面的接口. IFie ...
- Kotlin——最详细的数据类、密封类详解
在前面几个章节章节中,详细的讲解了Koltin中的接口类(Interface).枚举类(Enmu),还不甚了解的可以查看我的上一篇文章Kotlin--接口类.枚举类详解.当然,在Koltin中,除了接 ...
- 四种途径提高RabbitMQ传输消息数据的可靠性(一)
前言 RabbitMQ虽然有对队列及消息等的一些持久化设置,但其实光光只是这一个是不能够保障数据的可靠性的,下面我们提出这样的质疑: (1)RabbitMQ生产者是不知道自己发布的消息是否已经正确达到 ...
随机推荐
- 第八章 监控 Zabbix
1.1 YUM部署 Zabbix 2.4 1. 前期准备(省略) l Yum源的配置 cd /etc/yum.repos.d/; mkdir old;mv ./* old/ rpm -Uvh ...
- Eclipse中安装Jdk和配置Python
要借助Eclipse辅助工作,之前安装配置都是同事帮忙弄的,今天有空来整理一下安装配置步骤 一.安装JDK1.下载JDK,安装JDK,安装完毕,配置JDK环境变量 1)我的电脑右键-属性-高级-点击 ...
- expri on the testdisk
首先,根据GNU的编译知识,来分析下载下来的目录,虽然里面有很多win的,andriod的文件,就不要管了,考入centos里面去, 按下面顺序执行就ok了. 第一步执行顺序: #autoscan ...
- 百度地图api写在html上可以实现,在jsp上会出现Bmap未定义的问题
在html上引用时用:<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0& ...
- 【转】Python BeautifulSoup 中文乱码解决方法
这篇文章主要介绍了Python BeautifulSoup中文乱码问题的2种解决方法,需要的朋友可以参考下 解决方法一: 使用python的BeautifulSoup来抓取网页然后输出网页标题,但是输 ...
- crontab格式使用方式
第1列分钟1-59第2列小时1-23(0表示子夜)第3列日1-31第4列月1-12第5列星期0-6(0表示星期天)第6列要运行的命令 下面是crontab的格式:分 时 日 月 星期 要运行的命令 这 ...
- 第六十一节,html超链接和路径
html超链接和路径 学习要点: 1.超链接的属性 2.相对与绝对路径 3.锚点设置 本章主要探讨HTML5中文本元素 ...
- iOS开发QQ空间半透明效果的实现
//1.首先我们可以确定的是cell的半透明, /* white The grayscale value of the color object, specified as a value from ...
- 2016年团体程序设计天梯赛-决赛 L1-3. 出租(20)
下面是新浪微博上曾经很火的一张图: 一时间网上一片求救声,急问这个怎么破.其实这段代码很简单,index数组就是arr数组的下标,index[0]=2 对应 arr[2]=1,index[1]=0 对 ...
- offsetWidth,offsetHeight到底该如何理解?
1.对象的可见宽度(对象指body.div等) 2.offsetWidth可以返回div的宽 3.offsetWidth=width+padding+border(不包括margin外边距) 4.返回 ...

