Message_Block.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 //==========================================================================
00004 /**
00005  *  @file    Message_Block.h
00006  *
00007  *  Message_Block.h,v 4.114 2006/05/11 12:37:12 jwillemsen Exp
00008  *
00009  *  @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
00010  */
00011 //==========================================================================
00012 
00013 #ifndef ACE_MESSAGE_BLOCK_H
00014 #define ACE_MESSAGE_BLOCK_H
00015 
00016 #include /**/ "ace/pre.h"
00017 
00018 #include "ace/config-lite.h"
00019 #include "ace/ACE_export.h"
00020 
00021 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00022 # pragma once
00023 #endif /* ACE_LACKS_PRAGMA_ONCE */
00024 
00025 #include "ace/Default_Constants.h"
00026 #include "ace/Global_Macros.h"
00027 #include "ace/Time_Value.h"
00028 
00029 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00030 
00031 // Forward declaration.
00032 class ACE_Allocator;
00033 class ACE_Data_Block;
00034 class ACE_Lock;
00035 
00036 
00037 /**
00038  * @class ACE_Message_Block
00039  *
00040  * @brief Stores messages for use throughout ACE (particularly
00041  * in an ACE_Message_Queue).
00042  *
00043  * An ACE_Message_Block is modeled after the message data
00044  * structures used in System V STREAMS.  Its purpose is to
00045  * enable efficient manipulation of arbitrarily large messages
00046  * without incurring much memory copying overhead.  Here are the
00047  * main characteristics of an ACE_Message_Block:
00048  * - Contains a pointer to a reference-counted
00049  *   ACE_Data_Block, which in turn points to the actual data
00050  *   buffer.  This allows very flexible and efficient sharing of
00051  *   data by multiple ACE_Message_Block objects.
00052  * - One or more ACE_Message_Blocks can be linked to form a
00053  *    ``fragment chain.''
00054  * - ACE_Message_Blocks can be linked together in a doubly linked fashion
00055  *   to form a queue of messages (this is how ACE_Message_Queue works).
00056  *
00057  * @see C++NPv1, section 4.2; APG, section 12.3.2.
00058  */
00059 class ACE_Export ACE_Message_Block
00060 {
00061 public:
00062   friend class ACE_Data_Block;
00063 
00064   enum
00065   {
00066     // = Data and proto
00067     /// Undifferentiated data message
00068     MB_DATA     = 0x01,
00069     /// Undifferentiated protocol control
00070     MB_PROTO    = 0x02,
00071 
00072     // = Control messages
00073     /// Line break (regular and priority)
00074     MB_BREAK    = 0x03,
00075     /// Pass file pointer
00076     MB_PASSFP   = 0x04,
00077     /// Post an event to an event queue
00078     MB_EVENT    = 0x05,
00079     /// Generate process signal
00080     MB_SIG      = 0x06,
00081     /// ioctl; set/get params
00082     MB_IOCTL    = 0x07,
00083     /// Set various stream head options
00084     MB_SETOPTS  = 0x08,
00085 
00086     // = Control messages
00087     /// Acknowledge ioctl (high priority; go to head of queue)
00088     MB_IOCACK   = 0x81,
00089     /// Negative ioctl acknowledge
00090     MB_IOCNAK   = 0x82,
00091     /// Priority proto message
00092     MB_PCPROTO  = 0x83,
00093     /// Generate process signal
00094     MB_PCSIG    = 0x84,
00095     /// Generate read notification
00096     MB_READ     = 0x85,
00097     /// Flush your queues
00098     MB_FLUSH    = 0x86,
00099     /// Stop transmission immediately
00100     MB_STOP     = 0x87,
00101     /// Restart transmission after stop
00102     MB_START    = 0x88,
00103     /// Line disconnect
00104     MB_HANGUP   = 0x89,
00105     /// Fatal error used to set u.u_error
00106     MB_ERROR    = 0x8a,
00107     /// Post an event to an event queue
00108     MB_PCEVENT  = 0x8b,
00109 
00110     // = Message class masks
00111     /// Normal priority message mask
00112     MB_NORMAL   = 0x00,
00113     /// High priority control message mask
00114     MB_PRIORITY = 0x80,
00115     /// User-defined message mask
00116     MB_USER     = 0x200
00117   };
00118 
00119   typedef int ACE_Message_Type;
00120   typedef unsigned long Message_Flags;
00121 
00122   enum
00123   {
00124     /// Don't delete the data on exit since we don't own it.
00125     DONT_DELETE = 01,
00126     /// user defined flags start here
00127     USER_FLAGS = 0x1000
00128   };
00129 
00130   // = Initialization and termination.
00131   /// Create an empty message.
00132   ACE_Message_Block (ACE_Allocator *message_block_allocator = 0);
00133 
00134   /**
00135    * Create an ACE_Message_Block that owns the specified ACE_Data_Block
00136    * without copying it. If the @a flags is set to @c DONT_DELETE we
00137    * don't delete the ACE_Data_Block. It is left to the client's
00138    * responsibility to take care of the memory allocated for the
00139    * data_block
00140    */
00141   ACE_Message_Block (ACE_Data_Block *,
00142                      Message_Flags flags = 0,
00143                      ACE_Allocator *message_block_allocator = 0);
00144 
00145   /**
00146    * Create an ACE_Message_Block that refers to @a data without
00147    * copying it. The @a data memory will not be freed when this block is
00148    * destroyed; memory management of @a data is left to the caller.
00149    * Note that the @c size of the new ACE_Message_Block will be @a size, but
00150    * the @c length will be 0 until the write pointer is changed.
00151    */
00152   ACE_Message_Block (const char *data,
00153                      size_t size = 0,
00154                      unsigned long priority = ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY);
00155 
00156   /**
00157    * Create an initialized message of type @a type containing @a size
00158    * bytes.  The @a cont argument initializes the continuation field in
00159    * the ACE_Message_Block.  If @a data == 0 then this block allocates and
00160    * owns the block's memory, using @a allocator to get the data if it's
00161    * non-0.  If @a data != 0 then this block refers to that memory until
00162    * this this block ceases to exist; this object will not free @a data on
00163    * destruction.  If @a locking_strategy is non-0 then this is used
00164    * to protect regions of code that access shared state (e.g.,
00165    * reference counting) from race conditions.  Note that the @c size
00166    * of the ACE_Message_Block will be @a size, but the @c length will be 0
00167    * until the write pointer is set. The @a data_block_allocator is used to
00168    * allocate the data blocks while the @a allocator_strategy is used
00169    * to allocate the buffers contained by those. The
00170    * @a message_block_allocator is used to allocate new ACE_Message_Block
00171    * objects when the duplicate() method is called. If a
00172    * @a message_block_allocator is given, this ACE_Message_Block and
00173    * future ACE_Message_Block objects created by duplicate() will be
00174    * freed using this allocator when they are released.
00175    * @note If you use this allocator, the ACE_Message_Block you created
00176    * should have been created using this allocator because it will be
00177    * released to the same allocator.
00178    */
00179   ACE_Message_Block (size_t size,
00180                      ACE_Message_Type type = MB_DATA,
00181                      ACE_Message_Block *cont = 0,
00182                      const char *data = 0,
00183                      ACE_Allocator *allocator_strategy = 0,
00184                      ACE_Lock *locking_strategy = 0,
00185                      unsigned long priority = ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY,
00186                      const ACE_Time_Value &execution_time = ACE_Time_Value::zero,
00187                      const ACE_Time_Value &deadline_time = ACE_Time_Value::max_time,
00188                      ACE_Allocator *data_block_allocator = 0,
00189                      ACE_Allocator *message_block_allocator = 0);
00190 
00191   /**
00192    * A copy constructor. This constructor is a bit different. If the
00193    * incoming Message Block has a data block from the stack this
00194    * constructor does a deep copy ie. allocates a new data block on
00195    * the heap and does a copy of the data from the incoming message
00196    * block. As a final note, the alignment information is used to
00197    * align the data block if it is created afresh. If the incoming
00198    * <mb> has a data block has a data block allocated from the heap,
00199    * then this constructor just duplicates (ie. a shallow copy) the
00200    * data block of the incoming @a mb.
00201    */
00202   ACE_Message_Block (const ACE_Message_Block &mb,
00203                      size_t align);
00204 
00205   /**
00206    * Create a Message Block that assumes it has ownership of @a data,
00207    * but in reality it doesnt (i.e., cannot delete it since it didn't
00208    * malloc it!).  Note that the @c size of the Message_Block will
00209    * be @a size, but the <length>  will be 0 until <wr_ptr> is set.
00210    */
00211   int init (const char *data,
00212             size_t size = 0);
00213 
00214   /**
00215    * Create an initialized message of type @a type containing @a size
00216    * bytes.  The @a cont argument initializes the continuation field in
00217    * the <Message_Block>.  If @a data == 0 then we create and own the
00218    * @a data, using @a allocator_strategy to get the data if it's non-0.  If
00219    * @a data != 0 we assume that we have ownership of the @a data till
00220    * this object ceases to exist  (and don't delete it during
00221    * destruction).  If @a locking_strategy is non-0 then this is used
00222    * to protect regions of code that access shared state (e.g.,
00223    * reference counting) from race conditions.  Note that the <size>
00224    * of the <Message_Block> will be @a size, but the <length> will be 0
00225    * until  <wr_ptr> is set. The @a data_block_allocator is use to
00226    * allocate the data blocks while the @a allocator_strategy is used
00227    * to allocate the buffers contained by those.
00228    */
00229   int init (size_t size,
00230             ACE_Message_Type type = MB_DATA,
00231             ACE_Message_Block *cont = 0,
00232             const char *data = 0,
00233             ACE_Allocator *allocator_strategy = 0,
00234             ACE_Lock *locking_strategy = 0,
00235             unsigned long priority = ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY,
00236             const ACE_Time_Value &execution_time = ACE_Time_Value::zero,
00237             const ACE_Time_Value &deadline_time = ACE_Time_Value::max_time,
00238             ACE_Allocator *data_block_allocator = 0,
00239             ACE_Allocator *message_block_allocator = 0);
00240 
00241   /**
00242    * Delete all the resources held in the message.
00243    *
00244    * Note that <release()> is designed to release the continuation
00245    * chain; the destructor is not. See <release()> for details.
00246    */
00247   virtual ~ACE_Message_Block (void);
00248 
00249   // = Message Type accessors and mutators.
00250 
00251   /// Get type of the message.
00252   ACE_Message_Type msg_type (void) const;
00253 
00254   /// Set type of the message.
00255   void msg_type (ACE_Message_Type type);
00256 
00257   /// Find out what type of message this is.
00258   int is_data_msg (void) const;
00259 
00260   /// Find out what class of message this is (there are two classes,
00261   /// @c normal messages and @c high-priority messages).
00262   ACE_Message_Type msg_class (void) const;
00263 
00264   // = Message flag accessors and mutators.
00265   /// Bitwise-or the @a more_flags into the existing message flags and
00266   /// return the new value.
00267   Message_Flags set_flags (Message_Flags more_flags);
00268 
00269   /// Clear the message flag bits specified in @a less_flags and return
00270   /// the new value.
00271   Message_Flags clr_flags (Message_Flags less_flags);
00272 
00273   /// Get the current message flags.
00274   Message_Flags flags (void) const;
00275 
00276   // = Data Block flag accessors and mutators.
00277   /// Bitwise-or the <more_flags> into the existing message flags and
00278   /// return the new value.
00279   /* @todo: I think the following set of methods could not be used at
00280    *  all. May be they are useless. Let us have it so that we dont
00281    *  mess up memory management of the Message_Block. Somebody correct
00282    *  me if I am totally totally wrong..
00283    */
00284   Message_Flags set_self_flags (ACE_Message_Block::Message_Flags more_flags);
00285 
00286   /// Clear the message flag bits specified in @a less_flags and return
00287   /// the new value.
00288   Message_Flags clr_self_flags (ACE_Message_Block::Message_Flags less_flags);
00289 
00290   /// Get the current message flags.
00291   Message_Flags self_flags (void) const;
00292 
00293   /// Get priority of the message.
00294   unsigned long msg_priority (void) const;
00295 
00296   /// Set priority of the message.
00297   void msg_priority (unsigned long priority);
00298 
00299   /// Get execution time associated with the message.
00300   const ACE_Time_Value &msg_execution_time (void) const;
00301 
00302   /// Set execution time associated with the message.
00303   void msg_execution_time (const ACE_Time_Value &et);
00304 
00305   /// Get absolute time of deadline associated with the message.
00306   const ACE_Time_Value &msg_deadline_time (void) const;
00307 
00308   /// Set absolute time of deadline associated with the message.
00309   void msg_deadline_time (const ACE_Time_Value &dt);
00310 
00311   // = Deep copy and shallow copy methods.
00312 
00313   /// Return an exact "deep copy" of the message, i.e., create fresh
00314   /// new copies of all the Data_Blocks and continuations.
00315   virtual ACE_Message_Block *clone (Message_Flags mask = 0) const;
00316 
00317   /// Return a "shallow" copy that increments our reference count by 1.
00318   virtual ACE_Message_Block *duplicate (void) const;
00319 
00320   /**
00321    * Return a "shallow" copy that increments our reference count by 1.
00322    * This is similar to CORBA's <_duplicate> method, which is useful
00323    * if you want to eliminate lots of checks for NULL <mb> pointers
00324    * before calling <_duplicate> on them.
00325    */
00326   static ACE_Message_Block *duplicate (const ACE_Message_Block *mb);
00327 
00328   /**
00329    * Decrease the shared ACE_Data_Block's reference count by 1.  If the
00330    * ACE_Data_Block's reference count goes to 0, it is deleted.
00331    * In all cases, this ACE_Message_Block is deleted - it must have come
00332    * from the heap, or there will be trouble.
00333    *
00334    * release() is designed to release the continuation chain; the
00335    * destructor is not.  If we make the destructor release the
00336    * continuation chain by calling release() or delete on the message
00337    * blocks in the continuation chain, the following code will not
00338    * work since the message block in the continuation chain is not off
00339    * the heap:
00340    *
00341    *  ACE_Message_Block mb1 (1024);
00342    *  ACE_Message_Block mb2 (1024);
00343    *
00344    *  mb1.cont (&mb2);
00345    *
00346    * And hence, call release() on a dynamically allocated message
00347    * block. This will release all the message blocks in the
00348    * continuation chain.  If you call delete or let the message block
00349    * fall off the stack, cleanup of the message blocks in the
00350    * continuation chain becomes the responsibility of the user.
00351    *
00352    * @retval 0, always, and the object this method was invoked on is no
00353    *            longer valid.
00354    */
00355   virtual ACE_Message_Block *release (void);
00356 
00357   /**
00358    * This behaves like the non-static method <release>, except that it
00359    * checks if <mb> is 0.  This is similar to <CORBA::release>, which
00360    * is useful if you want to eliminate lots of checks for NULL
00361    * pointers before calling <release> on them.  Returns <mb>.
00362    */
00363   static ACE_Message_Block *release (ACE_Message_Block *mb);
00364 
00365   // = Operations on Message data
00366 
00367   /**
00368    * Copies data into this ACE_Message_Block. Data is copied into the
00369    * block starting at the current write pointer.
00370    *
00371    * @param buf  Pointer to the buffer to copy from.
00372    * @param n    The number of bytes to copy.
00373    *
00374    * @retval 0  on success; the write pointer is advanced by @arg n.
00375    * @retval -1 if the amount of free space following the write pointer
00376    *            in the block is less than @arg n. Free space can be checked
00377    *            by calling space().
00378    */
00379   int copy (const char *buf, size_t n);
00380 
00381   /**
00382    * Copies a 0-terminated character string into this ACE_Message_Block.
00383    * The string is copied into the block starting at the current write
00384    * pointer. The 0-terminator is included in the copied data.
00385    *
00386    * @param buf  Pointer to the character string to copy from.
00387    *
00388    * @retval 0  on success; the write pointer is advanced by the string's
00389    *            length, including the 0 terminator.
00390    * @retval -1 if the amount of free space following the write pointer
00391    *            in the block is less than required to hold the entire string.
00392    *            Free space can be checked by calling space().
00393    */
00394   int copy (const char *buf);
00395 
00396   /// Normalizes data in the top-level <Message_Block> to align with the base,
00397   /// i.e., it "shifts" the data pointed to by <rd_ptr> down to the <base> and
00398   /// then readjusts <rt_ptr> to point to <base> and <wr_ptr> to point
00399   /// to <base> + the length of the moved data.  Returns -1 and does
00400   /// nothing if the <rd_ptr> is > <wr_ptr>, else 0 on success.
00401   int crunch (void);
00402 
00403   /// Resets the Message Block data to contain nothing, i.e., sets the
00404   /// read and write pointers to align with the base.
00405   void reset (void);
00406 
00407   /// Access all the allocators in the message block.
00408   /// @@todo: Not sure whether we would need finer control while
00409   /// trying to access allocators ie. a method for every allocator.
00410   /**
00411    * This method returns the allocators only from the first message
00412    * block in the chain.
00413    *
00414    * @param allocator_strategy Strategy used to allocate the
00415    *                           underlying buffer
00416    *
00417    * @param data_block_allocator Strategy used to allocate the
00418    *                             underlying data block
00419    *
00420    * @param message_block_allocator Strategy used to allocate the
00421    *                                message block
00422    */
00423   void access_allocators (ACE_Allocator *&allocator_strategy,
00424                           ACE_Allocator *&data_block_allocator,
00425                           ACE_Allocator *&message_block_allocator);
00426 
00427   /// Reset all the allocators in the message block.
00428   /// @@todo: Not sure whether we would need finer control while
00429   /// trying to reset allocators ie. a method for every allocator.
00430   /**
00431    * This method resets the allocators in all the message blocks in
00432    * the chain.
00433    */
00434   void reset_allocators (ACE_Allocator *allocator_strategy = 0,
00435                          ACE_Allocator *data_block_allocator = 0,
00436                          ACE_Allocator *message_block_allocator = 0);
00437 
00438   /// Get message data.
00439   char *base (void) const;
00440 
00441   /// Set message data (doesn't reallocate).
00442   void base (char *data,
00443              size_t size,
00444              Message_Flags = DONT_DELETE);
00445 
00446   /// Return a pointer to 1 past the end of the allocated data in a message.
00447   char *end (void) const;
00448 
00449   /**
00450    * Return a pointer to 1 past the end of the allotted data in a message.
00451    * Allotted data may be less than allocated data  if a value smaller than
00452    * capacity() to is passed to size().
00453    */
00454   char *mark (void) const;
00455 
00456   /// Get the read pointer.
00457   char *rd_ptr (void) const;
00458 
00459   /// Set the read pointer to @a ptr.
00460   void rd_ptr (char *ptr);
00461 
00462   /// Set the read pointer ahead @a n bytes.
00463   void rd_ptr (size_t n);
00464 
00465   /// Get the write pointer.
00466   char *wr_ptr (void) const;
00467 
00468   /// Set the write pointer to @a ptr.
00469   void wr_ptr (char *ptr);
00470 
00471   /// Set the write pointer ahead <n> bytes.  This is used to compute
00472   /// the <length> of a message.
00473   void wr_ptr (size_t n);
00474 
00475   /** @name Message length and size operations
00476    *
00477    * Message length is (wr_ptr - rd_ptr).
00478    *
00479    * Message size is capacity of the message, including data outside
00480    * the [rd_ptr,wr_ptr] range.
00481    */
00482   //@{
00483   /// Get the length of the message
00484   size_t length (void) const;
00485 
00486   /// Set the length of the message
00487   void length (size_t n);
00488 
00489   /// Get the length of the <Message_Block>s, including chained
00490   /// <Message_Block>s.
00491   size_t total_length (void) const;
00492 
00493   /// Get the total number of bytes in all <Message_Block>s, including
00494   /// chained <Message_Block>s.
00495   size_t total_size (void) const;
00496 
00497   /// Get the total number of bytes and total length in all
00498   /// <Message_Block>s, including chained <Message_Block>s.
00499   void total_size_and_length (size_t &mb_size,
00500                               size_t &mb_length) const;
00501 
00502   /// Get the number of bytes in the top-level <Message_Block> (i.e.,
00503   /// does not consider the bytes in chained <Message_Block>s).
00504   size_t size (void) const;
00505 
00506   /**
00507    * Set the number of bytes in the top-level <Message_Block>,
00508    * reallocating space if necessary.  However, the <rd_ptr_> and
00509    * <wr_ptr_> remain at the original offsets into the buffer, even if
00510    * it is reallocated.  Returns 0 if successful, else -1.
00511    */
00512   int size (size_t length);
00513 
00514   /// Get the number of allocated bytes in all <Message_Block>, including
00515   /// chained <Message_Block>s.
00516   size_t total_capacity (void) const;
00517 
00518   /// Get the number of allocated bytes in the top-level <Message_Block>.
00519   size_t capacity (void) const;
00520 
00521   /// Get the number of bytes available after the <wr_ptr_> in the
00522   /// top-level <Message_Block>.
00523   size_t space (void) const;
00524   //@}
00525 
00526   // = ACE_Data_Block methods.
00527 
00528   /**
00529    * Get a pointer to the data block. Note that the ACE_Message_Block
00530    * still references the block; this call does not change the reference
00531    * count.
00532    */
00533   ACE_Data_Block *data_block (void) const;
00534 
00535   /**
00536    * Set a new data block pointer. The original ACE_Data_Block is released
00537    * as a result of this call. If you need to keep the original block, call
00538    * <replace_data_block> instead. Upon return, this ACE_Message_Block
00539    * holds a pointer to the new ACE_Data_Block, taking over the reference
00540    * you held on it prior to the call.
00541    */
00542   void data_block (ACE_Data_Block *);
00543 
00544   /// Set a new data block pointer. A pointer to the original ACE_Data_Block
00545   /// is returned, and not released (as it is with <data_block>).
00546   ACE_Data_Block *replace_data_block (ACE_Data_Block*);
00547 
00548   // = The continuation field chains together composite messages.
00549   /// Get the continuation field.
00550   ACE_Message_Block *cont (void) const;
00551 
00552   /// Set the continuation field.
00553   void cont (ACE_Message_Block *);
00554 
00555   // = Pointer to the <Message_Block> directly ahead in the ACE_Message_Queue.
00556   /// Get link to next message.
00557   ACE_Message_Block *next (void) const;
00558 
00559   /// Set link to next message.
00560   void next (ACE_Message_Block *);
00561 
00562   // = Pointer to the <Message_Block> directly behind in the ACE_Message_Queue.
00563   /// Get link to prev message.
00564   ACE_Message_Block *prev (void) const;
00565 
00566   /// Set link to prev message.
00567   void prev (ACE_Message_Block *);
00568 
00569   // = The locking strategy prevents race conditions.
00570   /// Get the locking strategy.
00571   ACE_Lock *locking_strategy (void);
00572 
00573   /// Set a new locking strategy and return the hold one.
00574   ACE_Lock *locking_strategy (ACE_Lock *);
00575 
00576   /// Get the current reference count.
00577   int reference_count (void) const;
00578 
00579   /// Dump the state of an object.
00580   void dump (void) const;
00581 
00582   /// Declare the dynamic allocation hooks.
00583   ACE_ALLOC_HOOK_DECLARE;
00584 
00585 protected:
00586   // = Internal initialization methods.
00587   /// Perform the actual initialization.
00588   ACE_Message_Block (size_t size,
00589                      ACE_Message_Type type,
00590                      ACE_Message_Block *cont,
00591                      const char *data,
00592                      ACE_Allocator *allocator_strategy,
00593                      ACE_Lock *locking_strategy,
00594                      Message_Flags flags,
00595                      unsigned long priority,
00596                      const ACE_Time_Value &execution_time,
00597                      const ACE_Time_Value &deadline_time,
00598                      ACE_Data_Block *db,
00599                      ACE_Allocator *data_block_allocator,
00600                      ACE_Allocator *message_block_allocator);
00601 
00602   /// Internal release implementation
00603   /// Returns 1 if the data block has to be destroyed.
00604   int release_i (ACE_Lock *lock);
00605 
00606   /// Perform the actual initialization.
00607   int init_i (size_t size,
00608               ACE_Message_Type type,
00609               ACE_Message_Block *cont,
00610               const char *data,
00611               ACE_Allocator *allocator_strategy,
00612               ACE_Lock *locking_strategy,
00613               Message_Flags flags,
00614               unsigned long priority,
00615               const ACE_Time_Value &execution_time,
00616               const ACE_Time_Value &deadline_time,
00617               ACE_Data_Block *db,
00618               ACE_Allocator *data_block_allocator,
00619               ACE_Allocator *message_block_allocator);
00620 
00621   /// Pointer to beginning of next read.
00622   size_t rd_ptr_;
00623 
00624   /// Pointer to beginning of next write.
00625   size_t wr_ptr_;
00626 
00627   /// Priority of message.
00628   unsigned long priority_;
00629 
00630 #if defined (ACE_HAS_TIMED_MESSAGE_BLOCKS)
00631   /// Execution time associated with the message.
00632   ACE_Time_Value execution_time_;
00633 
00634   /// Absolute deadline time for message.
00635   ACE_Time_Value deadline_time_;
00636 #endif /* ACE_HAS_TIMED_MESSAGE_BLOCKS */
00637 
00638   // = Links to other ACE_Message_Block *s.
00639   /// Pointer to next message block in the chain.
00640   ACE_Message_Block *cont_;
00641 
00642   /// Pointer to next message in the list.
00643   ACE_Message_Block *next_;
00644 
00645   /// Pointer to previous message in the list.
00646   ACE_Message_Block *prev_;
00647 
00648   /// Misc flags (e.g., DONT_DELETE and USER_FLAGS).
00649   ACE_Message_Block::Message_Flags flags_;
00650 
00651   /// Pointer to the reference counted data structure that contains the
00652   /// actual memory buffer.
00653   ACE_Data_Block *data_block_;
00654 
00655   /// The allocator used to destroy ourselves when release is called
00656   /// and create new message blocks on duplicate.
00657   ACE_Allocator *message_block_allocator_;
00658 
00659 private:
00660   // = Disallow these operations for now (use <clone> instead).
00661   ACE_Message_Block &operator= (const ACE_Message_Block &);
00662   ACE_Message_Block (const ACE_Message_Block &);
00663 };
00664 
00665 /**
00666  * @class ACE_Data_Block
00667  *
00668  * @brief Stores the data payload that is accessed via one or more
00669  * ACE_Message_Block's.
00670  *
00671  * This data structure is reference counted to maximize
00672  * sharing.  It also contains the <locking_strategy_> (which
00673  * protects the reference count from race conditions in
00674  * concurrent programs) and the <allocation_strategy_> (which
00675  * determines what memory pool is used to allocate the memory).
00676  */
00677 class ACE_Export ACE_Data_Block
00678 {
00679 public:
00680   // = Initialization and termination methods.
00681   /// Default "do-nothing" constructor.
00682   ACE_Data_Block (void);
00683 
00684   /// Initialize.
00685   ACE_Data_Block (size_t size,
00686                   ACE_Message_Block::ACE_Message_Type msg_type,
00687                   const char *msg_data,
00688                   ACE_Allocator *allocator_strategy,
00689                   ACE_Lock *locking_strategy,
00690                   ACE_Message_Block::Message_Flags flags,
00691                   ACE_Allocator *data_block_allocator);
00692 
00693   /// Delete all the resources held in the message.
00694   virtual ~ACE_Data_Block (void);
00695 
00696   /// Get type of the message.
00697   ACE_Message_Block::ACE_Message_Type msg_type (void) const;
00698 
00699   /// Set type of the message.
00700   void msg_type (ACE_Message_Block::ACE_Message_Type type);
00701 
00702   /// Get message data pointer
00703   char *base (void) const;
00704 
00705   /// Set message data pointer (doesn't reallocate).
00706   void base (char *data,
00707              size_t size,
00708              ACE_Message_Block::Message_Flags mflags = ACE_Message_Block::DONT_DELETE);
00709 
00710   /// Return a pointer to 1 past the end of the allocated data in a message.
00711   char *end (void) const;
00712 
00713   /**
00714    * Return a pointer to 1 past the end of the allotted data in a message.
00715    * The allotted data may be less than allocated data if <size()> is passed
00716    * an argument less than <capacity()>.
00717    */
00718   char *mark (void) const;
00719 
00720   // = Message size is the total amount of space alloted.
00721 
00722   /// Get the total amount of allotted space in the message.  The amount of
00723   /// allotted space may be less than allocated space.
00724   size_t size (void) const;
00725 
00726   /// Set the total amount of space in the message.  Returns 0 if
00727   /// successful, else -1.
00728   int size (size_t length);
00729 
00730   /// Get the total amount of allocated space.
00731   size_t capacity (void) const;
00732 
00733   /**
00734    * Return an exact "deep copy" of the message, i.e., create fresh
00735    * new copies of all the Data_Blocks and continuations.
00736    * Notice that Data_Blocks can act as "Prototypes", i.e. derived
00737    * classes can override this method and create instances of
00738    * themselves.
00739    */
00740   virtual ACE_Data_Block *clone (ACE_Message_Block::Message_Flags mask = 0) const;
00741 
00742   /**
00743    * As clone above, but it does not copy the contents of the buffer,
00744    * i.e., create a new Data_Block of the same dynamic type, with the
00745    * same allocator, locking_strategy, and with the same amount of
00746    * storage available but the buffer is unitialized.
00747    */
00748   virtual ACE_Data_Block *clone_nocopy (ACE_Message_Block::Message_Flags mask = 0) const;
00749 
00750   /// Return a "shallow" copy that increments our reference count by 1.
00751   ACE_Data_Block *duplicate (void);
00752 
00753   /**
00754    * Decrease the shared reference count by 1.  If the reference count
00755    * is > 0 then return this; else if reference count == 0 then delete
00756    * <this> and <mb> and return 0.  Behavior is undefined if reference
00757    * count < 0.
00758    */
00759   ACE_Data_Block *release (ACE_Lock *lock = 0);
00760 
00761   // = Message flag accessors and mutators.
00762   /// Bitwise-or the <more_flags> into the existing message flags and
00763   /// return the new value.
00764   ACE_Message_Block::Message_Flags set_flags (ACE_Message_Block::Message_Flags more_flags);
00765 
00766   /// Clear the message flag bits specified in <less_flags> and return
00767   /// the new value.
00768   ACE_Message_Block::Message_Flags clr_flags (ACE_Message_Block::Message_Flags less_flags);
00769 
00770   /// Get the current message flags.
00771   ACE_Message_Block::Message_Flags flags (void) const;
00772 
00773   /// Obtain the allocator strategy.
00774   ACE_Allocator *allocator_strategy (void) const;
00775 
00776   // = The locking strategy prevents race conditions.
00777   /// Get the locking strategy.
00778   ACE_Lock *locking_strategy (void);
00779 
00780   /// Set a new locking strategy and return the hold one.
00781   ACE_Lock *locking_strategy (ACE_Lock *);
00782 
00783   /// Dump the state of an object.
00784   void dump (void) const;
00785 
00786   /// Get the current reference count.
00787   int reference_count (void) const;
00788 
00789   /// Get the allocator used to create this object
00790   ACE_Allocator *data_block_allocator (void) const;
00791 
00792 protected:
00793   /// Internal release implementation
00794   virtual ACE_Data_Block *release_i (void);
00795 
00796   /// Internal get the current reference count.
00797   int reference_count_i (void) const;
00798 
00799   /**
00800    * Decrease the reference count, but don't delete the object.
00801    * Returns 0 if the object should be removed.
00802    * If <lock> is equal to the locking strategy then we assume that
00803    * the lock is beign held by the current thread; this is used to
00804    * release all the data blocks in a chain while holding a single
00805    * lock.
00806    */
00807   friend class ACE_Message_Block;
00808   ACE_Data_Block *release_no_delete (ACE_Lock *lock);
00809 
00810   /// Type of message.
00811   ACE_Message_Block::ACE_Message_Type type_;
00812 
00813   /// Current size of message block.
00814   size_t cur_size_;
00815 
00816   /// Total size of buffer.
00817   size_t max_size_;
00818 
00819   /// Misc flags (e.g., DONT_DELETE and USER_FLAGS).
00820   ACE_Message_Block::Message_Flags flags_;
00821 
00822   /// Pointer To beginning of message payload.
00823   char *base_;
00824 
00825   // = Strategies.
00826   /**
00827    * Pointer to the allocator defined for this ACE_Data_Block.  Note
00828    * that this pointer is shared by all owners of this
00829    * ACE_Data_Block.
00830    */
00831   ACE_Allocator *allocator_strategy_;
00832 
00833   /**
00834    * Pointer to the locking strategy defined for this
00835    * ACE_Data_Block.  This is used to protect regions of code that
00836    * access shared ACE_Data_Block state.  Note that this lock is
00837    * shared by all owners of the ACE_Data_Block's data.
00838    */
00839   ACE_Lock *locking_strategy_;
00840 
00841   /**
00842    * Reference count for this ACE_Data_Block, which is used to avoid
00843    * deep copies (i.e., <clone>).  Note that this pointer value is
00844    * shared by all owners of the <Data_Block>'s data, i.e., all the
00845    * ACE_Message_Blocks.
00846    */
00847   int reference_count_;
00848 
00849   /// The allocator use to destroy ourselves.
00850   ACE_Allocator *data_block_allocator_;
00851 
00852 private:
00853   // = Disallow these operations.
00854   ACE_Data_Block &operator= (const ACE_Data_Block &);
00855   ACE_Data_Block (const ACE_Data_Block &);
00856 };
00857 
00858 /**
00859  * @class ACE_Dynamic_Message_Strategy
00860  *
00861  * @brief An abstract base class which provides dynamic priority
00862  * evaluation methods for use by the ACE_Dynamic_Message_Queue
00863  * class or any other class which needs to manage the priorities
00864  * of a collection of ACE_Message_Block's dynamically.
00865  *
00866  * Methods for deadline and laxity based priority evaluation are
00867  * provided.  These methods assume a specific partitioning of
00868  * the message priority number into a higher order dynamic bit
00869  * field and a lower order static priority bit field.  The
00870  * default partitioning assumes an unsigned dynamic message
00871  * priority field of 22 bits and an unsigned static message
00872  * priority field of 10 bits.  This corresponds to the initial
00873  * values of the static class members.  To provide a different
00874  * partitioning, assign a different set of values to the static
00875  * class memebers before using the static member functions.
00876  */
00877 class ACE_Export ACE_Dynamic_Message_Strategy
00878 {
00879 public:
00880 
00881   // = Message priority status
00882 
00883   // Values are defined as bit flags so that status combinations may
00884   // be specified easily.
00885 
00886   enum Priority_Status
00887   {
00888     /// Message can still make its deadline
00889     PENDING     = 0x01,
00890     /// Message cannot make its deadline
00891     LATE        = 0x02,
00892     /// Message is so late its priority is undefined
00893     BEYOND_LATE = 0x04,
00894     /// Mask to match any priority status
00895     ANY_STATUS  = 0x07
00896   };
00897 
00898   /// Constructor.
00899   ACE_Dynamic_Message_Strategy (unsigned long static_bit_field_mask,
00900                                 unsigned long static_bit_field_shift,
00901                                 unsigned long dynamic_priority_max,
00902                                 unsigned long dynamic_priority_offset);
00903 
00904   /// Virtual destructor.
00905   virtual ~ACE_Dynamic_Message_Strategy (void);
00906 
00907   /// Updates the message's priority and returns its priority status.
00908   Priority_Status priority_status (ACE_Message_Block &mb,
00909                                    const ACE_Time_Value &tv);
00910 
00911   /// Get static bit field mask.
00912   unsigned long static_bit_field_mask (void) const;
00913 
00914   /// Set static bit field mask.
00915   void static_bit_field_mask (unsigned long);
00916 
00917   /// Get left shift value to make room for static bit field.
00918   unsigned long static_bit_field_shift (void) const;
00919 
00920   /// Set left shift value to make room for static bit field.
00921   void static_bit_field_shift (unsigned long);
00922 
00923   /// Get maximum supported priority value.
00924   unsigned long dynamic_priority_max (void) const;
00925 
00926   /// Set maximum supported priority value.
00927   void dynamic_priority_max (unsigned long);
00928 
00929   /// Get offset to boundary between signed range and unsigned range.
00930   unsigned long dynamic_priority_offset (void) const;
00931 
00932   /// Set offset to boundary between signed range and unsigned range.
00933   void dynamic_priority_offset (unsigned long);
00934 
00935   /// Dump the state of the strategy.
00936   virtual void dump (void) const;
00937 
00938 protected:
00939   /// Hook method for dynamic priority conversion.
00940   virtual void convert_priority (ACE_Time_Value &priority,
00941                                  const ACE_Message_Block &mb) = 0;
00942 
00943   /// This is a bit mask with all ones in the static bit field.
00944   unsigned long static_bit_field_mask_;
00945 
00946   /**
00947    * This is a left shift value to make room for static bit field:
00948    * this value should be the logarithm base 2 of
00949    * (static_bit_field_mask_ + 1).
00950    */
00951   unsigned long static_bit_field_shift_;
00952 
00953   /// Maximum supported priority value.
00954   unsigned long dynamic_priority_max_;
00955 
00956   /// Offset to boundary between signed range and unsigned range.
00957   unsigned long dynamic_priority_offset_;
00958 
00959   /// Maximum late time value that can be represented.
00960   ACE_Time_Value max_late_;
00961 
00962   /// Minimum pending time value that can be represented.
00963   ACE_Time_Value min_pending_;
00964 
00965   /// Time value by which to shift pending priority.
00966   ACE_Time_Value pending_shift_;
00967 };
00968 
00969 /**
00970  * @class ACE_Deadline_Message_Strategy
00971  *
00972  * @brief Deadline based message priority strategy.
00973  *
00974  * Assigns dynamic message priority according to time to deadline.  The
00975  * message priority is divided into high and low order bit fields.  The
00976  * high order bit field is used for dynamic message priority, which is
00977  * updated whenever the convert_priority() method is called.  The
00978  * low order bit field is used for static message priority and is left
00979  * unchanged.  The partitioning of the priority value into high and low
00980  * order bit fields is done according to the arguments passed to the
00981  * strategy object's constructor.
00982  */
00983 class ACE_Export ACE_Deadline_Message_Strategy : public ACE_Dynamic_Message_Strategy
00984 {
00985 public:
00986   /// Ctor, with all arguments defaulted.
00987   ACE_Deadline_Message_Strategy (unsigned long static_bit_field_mask = 0x3FFUL,       // 2^(10) - 1
00988                                  unsigned long static_bit_field_shift = 10,           // 10 low order bits
00989                                  unsigned long dynamic_priority_max = 0x3FFFFFUL,     // 2^(22)-1
00990                                  unsigned long dynamic_priority_offset = 0x200000UL); // 2^(22-1)
00991 
00992   /// Virtual dtor.
00993   virtual ~ACE_Deadline_Message_Strategy (void);
00994 
00995   /// Dynamic priority conversion function based on time to deadline.
00996   virtual void convert_priority (ACE_Time_Value &priority,
00997                                  const ACE_Message_Block &mb);
00998 
00999   /// Dump the state of the strategy.
01000   virtual void dump (void) const;
01001 };
01002 
01003 /**
01004  * @class ACE_Laxity_Message_Strategy
01005  *
01006  * @brief Laxity based message priority strategy.
01007  *
01008  * Assigns dynamic message priority according to laxity (time to
01009  * deadline minus worst case execution time).  The message priority is
01010  * divided into high and low order bit fields.  The high order
01011  * bit field is used for dynamic message priority, which is
01012  * updated whenever the convert_priority() method is called.  The
01013  * low order bit field is used for static message priority and is left
01014  * unchanged.  The partitioning of the priority value into high and low
01015  * order bit fields is done according to the arguments passed to the
01016  * strategy object's constructor.
01017  */
01018 class ACE_Export ACE_Laxity_Message_Strategy : public ACE_Dynamic_Message_Strategy
01019 {
01020 public:
01021   /// Ctor, with all arguments defaulted.
01022   ACE_Laxity_Message_Strategy (unsigned long static_bit_field_mask = 0x3FFUL,       // 2^(10) - 1
01023                                unsigned long static_bit_field_shift = 10,           // 10 low order bits
01024                                unsigned long dynamic_priority_max = 0x3FFFFFUL,     // 2^(22)-1
01025                                unsigned long dynamic_priority_offset = 0x200000UL); // 2^(22-1)
01026 
01027   /// virtual dtor.
01028   virtual ~ACE_Laxity_Message_Strategy (void);
01029 
01030   /// Dynamic priority conversion function based on laxity.
01031   virtual void convert_priority (ACE_Time_Value &priority,
01032                                  const ACE_Message_Block &mb);
01033 
01034   /// Dump the state of the strategy.
01035   virtual void dump (void) const;
01036 };
01037 
01038 ACE_END_VERSIONED_NAMESPACE_DECL
01039 
01040 #if defined (__ACE_INLINE__)
01041 #include "ace/Message_Block.inl"
01042 #endif /* __ACE_INLINE__ */
01043 
01044 #include "ace/Message_Block_T.h"
01045 
01046 #include /**/ "ace/post.h"
01047 
01048 #endif /* ACE_MESSAGE_BLOCK_H */

Generated on Thu Nov 9 09:41:56 2006 for ACE by doxygen 1.3.6