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_,'\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;
}

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 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM