ACE_Message_Block在Ace中用来表示消息的存放空间,可用做网络通信中的消息缓冲区,使用非常频繁,下面将在如下方简单的介绍一下ACE_Message_Block相关功能。
- 创建消息块
- 释放消息块
- 从消息块中读写数据
- 数据的拷贝
- 其它常用函数
1。创建消息块
创建消息块的方式比较灵活,常用的有以下几种方式 :
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()方法实际地创建整个消息块的新副本,包括它的数据块和附加部分;也就是说,这是一次"深拷贝"。
2。释放消息块
一旦使用完消息块,程序员可以调用它的release()方法来释放它。
- 如果消息数据内存是由该消息块分配的,调用release()方法就也会释放此内存。
- 如果消息块是引用计数的,release()就会减少计数,直到到达0为止;之后消息块和与它相关联的数据块才从内存中被移除。
- 如果消息块是通过共享已分配的底层数据块创建的,底层数据块不会被释放。
无论消息块是哪种方式创建的,只要在使用完后及时调用release()函数,就能确保相应的内存能正确的释放。
3。从消息块中读写数据
ACE_Message_Block提供了两个指针函数以供程序员进行读写操作,rd_ptr()指向可读的数据块地址,wr_ptr()指向可写的数据块地址,默认情况下都执行数据块的首地址。下面的例子简单了演示它的使用方法。
ACE_Message_Block *mb=new ACE_Message_Block(30);
ACE_OS::sprintf(mb->wr_ptr(),"%s","hello");
ACE_OS::printf("%s\n",mb->rd_ptr());
mb->wr_ptr(5);
ACE_OS::sprintf(mb->wr_ptr(),"%s","world");
ACE_OS::printf("%s\n",mb->rd_ptr());
mb->rd_ptr(5);
ACE_OS::printf("%s\n",mb->rd_ptr());
mb->release();
输出:
hello
helloworld
world
4。数据的拷贝
一般的数据的拷贝可以通过函数来实现数据的拷贝,copy()还会保证wr_ptr()的更新,使其指向缓冲区的新末尾处。
下面的例子演示了copy()函数的用法。
mb->copy("hello");
mb->copy("123",4);
注意:由于c++是以'\0'作为字符串结束标志的,对于上面的例子,底层数据块中保存的是"hello\0123\0",而用ACE_OS::printf("%s\n",mb->rd_ptr ());打印出来的结果是"hello",使用copy函数进行字符串连接的时候需要注意。
5。其它常用函数
- length() 返回当前的数据长度
- next() 获取和设置下一个ACE_Message_Block的链接。(用来建立消息队列非常有用)
- space() 获取剩余可用空间大小
- size() 获取和设置数据存储空间大小。
#include "ace/Synch.h" ///ace::sleep
#include "ace/Task.h"
#include "ace/Message_Block.h"
//the consumer task
class consumer: public ACE_Task<ACE_MT_SYNCH>
{
public:
int open(void*)
{
ACE_DEBUG((LM_DEBUG,"(%t) producer task opened\n"));
//activate the task
activate(THR_NEW_LWP,1);
return 0;
}
//the service processing routine
int svc(void)
{
//get ready to receive message from producer
ACE_Message_Block *mb=0;
do
{
mb=0;
//get message from underlying queue
getq(mb);
ACE_DEBUG((LM_DEBUG,"(%t) got message: %d from remote task\n",*mb->rd_ptr()));
} while (*mb->rd_ptr()<10);
return 0;
}
int close(u_long)
{
ACE_DEBUG((LM_DEBUG,"consumer closes down\n"));
return 0;
}
};
class producer: public ACE_Task<ACE_MT_SYNCH>
{
public:
producer(consumer *con):consumer_(con),data_(0)
{
mb_=new ACE_Message_Block((char*)&data_,sizeof(data_));
}
int open(void*)
{
ACE_DEBUG((LM_DEBUG,"(%t) producer task opened\n"));
//activate the task
activate(THR_NEW_LWP,1);
return 0;
}
//the service processing routine
int svc(void)
{
while(data_<11)
{
//send message to consumer
ACE_DEBUG((LM_DEBUG,"(%t) sending message: %d to remote task\n",data_));
consumer_->putq(mb_);
//go to sleep for a sec
ACE_OS::sleep(1);
data_++;
}
return 0;
}
int close(u_long)
{
ACE_DEBUG((LM_DEBUG,"producer closes down\n"));
return 0;
}
private:
char data_;
consumer *consumer_;
ACE_Message_Block *mb_;
};
int main(int argc, char *argv[])
{
consumer *_consumer=new consumer;
producer *_producer=new producer(_consumer);
_producer->open(0);
_consumer->open(0);
//wait for all the tasks to exit.
ACE_Thread_Manager::instance()->wait();
return 0;
}
(376) sending message: 0 to remote task
(8544) got message: 0 from remote task
以上内容转自于网络。