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 */
1.2.14 written by Dimitri van Heesch,
© 1997-2002