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 */