ACE学习(七)ACE_Message_Queue

来源:互联网 发布:mac怎么打希腊字母 编辑:程序博客网 时间:2024/06/05 14:14

ACE_Message_Queue

 

消息队列的使用已经在前面的ACE_Semaphore中使用到了,其中使用的就是它的典型用法。

ACE_Message_Queue

/**
 * @class ACE_Message_Queue
 *
 * @brief A message queueing facility with parameterized synchronization
 * capability. ACE_Message_Queue is modeled after the queueing facilities
 * in System V STREAMs.
 *
 * ACE_Message_Queue is the primary queueing facility for
 * messages in the ACE framework.  It's one template argument parameterizes
 * the queue's synchronization. The argument specifies a synchronization
 * strategy. The two main strategies available for ACE_SYNCH_DECL are:
 *   -# ACE_MT_SYNCH: all operations are thread-safe
 *   -# ACE_NULL_SYNCH: no synchronization and no locking overhead
 *
 * All data passing through ACE_Message_Queue is in the form of
 * ACE_Message_Block objects. @sa ACE_Message_Block.
 */

 

1.与System V的消息队列模型不同

 

ACE_Message_Queue的模型是仿照System V streams提供的排队设施设计的,但是与System V排队设施不同,使用ACE的排队设施,可以在单个进程中进行高效的线程间通信,但是没有提供用于进程间通信的排队设施。

 

 

2.基于traits策略的类的设计

 

为了实现线程安全,经常要实现多种版本的库,多线程库、单线程库,这样会给库的维护与开发带来很多问题,而在ACE中经常看到ACE_<ACE_XXX>这种用法,ACE_XXX类代表的是一系列的宏定义,这些宏决定了使用哪种策略。例如消息队列的使用要public ACE_Task<ACE_MT_SYNCH>而参数ACE_MT_SYNCH的定义如下:

class ACE_Export ACE_MT_SYNCH
{
public:
  typedef ACE_Thread_Mutex MUTEX;
  typedef ACE_Null_Mutex NULL_MUTEX;
  typedef ACE_Process_Mutex PROCESS_MUTEX;
  typedef ACE_Recursive_Thread_Mutex RECURSIVE_MUTEX;
  typedef ACE_RW_Thread_Mutex RW_MUTEX;
  typedef ACE_Condition_Thread_Mutex CONDITION;
  typedef ACE_Condition_Recursive_Thread_Mutex RECURSIVE_CONDITION;
  typedef ACE_Thread_Semaphore SEMAPHORE;
  typedef ACE_Null_Semaphore NULL_SEMAPHORE;
};

可以对比下另外一个参数ACE_NULL_SYNCH

class ACE_Export ACE_NULL_SYNCH
{
public:
  typedef ACE_Null_Mutex MUTEX;
  typedef ACE_Null_Mutex NULL_MUTEX;
  typedef ACE_Null_Mutex PROCESS_MUTEX;
  typedef ACE_Null_Mutex RECURSIVE_MUTEX;
  typedef ACE_Null_Mutex RW_MUTEX;
  typedef ACE_Null_Condition CONDITION;
  typedef ACE_Null_Condition RECURSIVE_CONDITION;
  typedef ACE_Null_Semaphore SEMAPHORE;
  typedef ACE_Null_Mutex NULL_SEMAPHORE;
};

简单比较下第一个宏MUTEX的定义,在MT_SYNCH(多线程同步)里面为ACE_Thread_Mutex 而在NULL_SYNCH(单线程同步)里面为ACE_Null_Mutex,而ACE_NULL_Mutex是一个“方法都没有实现的互斥锁”,ACE_NULL_Mutex与ACE_Thread_Mutex 有相同的接口,但是没有实现任何方法,所以使用起来接口一样,但效果不一样。这样就把一个类ACE_MT_SYNCH作为参数,从而决定了ACE_Task的消息队列的实现,从而简化了库的设计。ACE中大量这样的用法,依照具体的的类型产生相应的模板或者模板函数,通过模板参数实现根据环境需要改变其行为方式,通过静态绑定来进一步提高效率。这种策略叫做traits策略,与strategy有很大不同:traits 策略的替换是在编译时确定的,strategy是通过动态绑定实现的。


 

3.消息块ACE_Message_Block的使用

 

消息块是消息队列中的固定的对象结构,可以把消息块当成一种高级的数据缓存区,支持引用计数和数据共享,每个消息块都含有两个指针:rd_ptr()和指向要读取的下一个字节:wr_ptr()。一旦使用完了消息块,要用release()方法释放它,从而使引用计数减一,当计数到达0的时候,ACE会自动释放分配的内存。消息块还有一个类型字段,可以通过msg_type()修改设置,还提供了一个duplicate()方法,用以创建一个新的指向块的数据的引用,并使引用计数加一,另外还提供了clone()方法,用以创建消息块的深度拷贝。

/**
 * @class ACE_Message_Block
 *
 * @brief Stores messages for use throughout ACE (particularly
 * in an ACE_Message_Queue).
 *
 * An ACE_Message_Block is modeled after the message data
 * structures used in System V STREAMS.  Its purpose is to
 * enable efficient manipulation of arbitrarily large messages
 * without incurring much memory copying overhead.  Here are the
 * main characteristics of an ACE_Message_Block:
 * - Contains a pointer to a reference-counted
 *   ACE_Data_Block, which in turn points to the actual data
 *   buffer.  This allows very flexible and efficient sharing of
 *   data by multiple ACE_Message_Block objects.
 * - One or more ACE_Message_Blocks can be linked to form a
 *    ``fragment chain.''
 * - ACE_Message_Blocks can be linked together in a doubly linked fashion
 *   to form a queue of messages (this is how ACE_Message_Queue works).
 *
 * @see C++NPv1, section 4.2; APG, section 12.3.2.
 */

 

4.ACE_Message_Block Demo

// message_block.cpp#include "ace/Task.h"int ACE_TMAIN(int, ACE_TCHAR *[]){//use copy ACE_Message_Block *mb;ACE_NEW_RETURN(mb, ACE_Message_Block(128), -1);const char *deviceAddr = "Dev#12";mb->copy(deviceAddr, ACE_OS::strlen(deviceAddr) + 1);ACE_DEBUG((LM_DEBUG, ACE_TEXT("Devide addr -->%s\n"), mb->rd_ptr()));//use  wr_ptr()ACE_Message_Block *mb2;ACE_NEW_RETURN(mb2, ACE_Message_Block(128), -1);const char *commandSeq = "commandSeq#14";ACE_OS::sprintf(mb2->wr_ptr(), commandSeq);//move the wr_ptr() forward in the buffer by the amount of data we put in.mb2->wr_ptr(ACE_OS::strlen(commandSeq)+1);ACE_DEBUG((LM_DEBUG, ACE_TEXT("Command Sequence -->%s\n"), mb2->rd_ptr()));//the rd_ptr() also need forwardmb2->rd_ptr(ACE_OS::strlen(mb2->rd_ptr())+1);mb2->release();//the use of msg_type()//send a hangup notification to the receiver.ACE_NEW_RETURN(mb2, ACE_Message_Block(128, ACE_Message_Block::MB_HANGUP), -1);//send an error notification to the receiver.mb2->msg_type(ACE_Message_Block::MB_ERROR);return 0;}


 


5.参考:


《C++NPv1》
http://jnn.blogbus.com/logs/180955.html