zoukankan      html  css  js  c++  java
  • 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 (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_,'',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;
    }

    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 

  • 相关阅读:
    【JZOJ6223】【20190617】互膜
    【JZOJ6225】【20190618】计数
    【JZOJ6226】【20190618】纳什均衡
    【JZOJ6210】【20190612】wsm
    【学习笔记】析合树
    【JZOJ6206】【20190610】二分图边染色
    【loj3123】【CTS2019】重复
    【loj3120】【CTS2019】珍珠
    【loj3119】【CTS2019】随机立方体
    CTS&&APIO2019爆零记
  • 原文地址:https://www.cnblogs.com/hgwang/p/5940168.html
Copyright © 2011-2022 走看看