Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Message_Block.h

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

Generated on Mon Jun 16 11:20:22 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002