00001 // -*- C++ -*- 00002 00003 //========================================================================== 00004 /** 00005 * @file Message_Block.h 00006 * 00007 * $Id: Message_Block.h 80826 2008-03-04 14:51:23Z wotte $ 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 * @a 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 @a 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 @a size 00224 * of the <Message_Block> will be @a size, but the @a 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 @a 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 @a 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 @a 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 @a 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 <rd_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 @a 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 (if @a max_size is zero) but the buffer is unitialized. 00747 * If @a max_size is specified other than zero, it will be used when 00748 * creating the new data block. 00749 */ 00750 virtual ACE_Data_Block *clone_nocopy (ACE_Message_Block::Message_Flags mask = 0, 00751 size_t max_size = 0) const; 00752 00753 /// Return a "shallow" copy that increments our reference count by 1. 00754 ACE_Data_Block *duplicate (void); 00755 00756 /** 00757 * Decrease the shared reference count by 1. If the reference count 00758 * is > 0 then return this; else if reference count == 0 then delete 00759 * @c this and @a mb and return 0. Behavior is undefined if reference 00760 * count < 0. 00761 */ 00762 ACE_Data_Block *release (ACE_Lock *lock = 0); 00763 00764 // = Message flag accessors and mutators. 00765 /// Bitwise-or the <more_flags> into the existing message flags and 00766 /// return the new value. 00767 ACE_Message_Block::Message_Flags set_flags (ACE_Message_Block::Message_Flags more_flags); 00768 00769 /// Clear the message flag bits specified in <less_flags> and return 00770 /// the new value. 00771 ACE_Message_Block::Message_Flags clr_flags (ACE_Message_Block::Message_Flags less_flags); 00772 00773 /// Get the current message flags. 00774 ACE_Message_Block::Message_Flags flags (void) const; 00775 00776 /// Obtain the allocator strategy. 00777 ACE_Allocator *allocator_strategy (void) const; 00778 00779 // = The locking strategy prevents race conditions. 00780 /// Get the locking strategy. 00781 ACE_Lock *locking_strategy (void); 00782 00783 /// Set a new locking strategy and return the hold one. 00784 ACE_Lock *locking_strategy (ACE_Lock *); 00785 00786 /// Dump the state of an object. 00787 void dump (void) const; 00788 00789 /// Get the current reference count. 00790 int reference_count (void) const; 00791 00792 /// Get the allocator used to create this object 00793 ACE_Allocator *data_block_allocator (void) const; 00794 00795 protected: 00796 /// Internal release implementation 00797 virtual ACE_Data_Block *release_i (void); 00798 00799 /// Internal get the current reference count. 00800 int reference_count_i (void) const; 00801 00802 /** 00803 * Decrease the reference count, but don't delete the object. 00804 * Returns 0 if the object should be removed. 00805 * If <lock> is equal to the locking strategy then we assume that 00806 * the lock is beign held by the current thread; this is used to 00807 * release all the data blocks in a chain while holding a single 00808 * lock. 00809 */ 00810 friend class ACE_Message_Block; 00811 ACE_Data_Block *release_no_delete (ACE_Lock *lock); 00812 00813 /// Type of message. 00814 ACE_Message_Block::ACE_Message_Type type_; 00815 00816 /// Current size of message block. 00817 size_t cur_size_; 00818 00819 /// Total size of buffer. 00820 size_t max_size_; 00821 00822 /// Misc flags (e.g., DONT_DELETE and USER_FLAGS). 00823 ACE_Message_Block::Message_Flags flags_; 00824 00825 /// Pointer To beginning of message payload. 00826 char *base_; 00827 00828 // = Strategies. 00829 /** 00830 * Pointer to the allocator defined for this ACE_Data_Block. Note 00831 * that this pointer is shared by all owners of this 00832 * ACE_Data_Block. 00833 */ 00834 ACE_Allocator *allocator_strategy_; 00835 00836 /** 00837 * Pointer to the locking strategy defined for this 00838 * ACE_Data_Block. This is used to protect regions of code that 00839 * access shared ACE_Data_Block state. Note that this lock is 00840 * shared by all owners of the ACE_Data_Block's data. 00841 */ 00842 ACE_Lock *locking_strategy_; 00843 00844 /** 00845 * Reference count for this ACE_Data_Block, which is used to avoid 00846 * deep copies (i.e., <clone>). Note that this pointer value is 00847 * shared by all owners of the <Data_Block>'s data, i.e., all the 00848 * ACE_Message_Blocks. 00849 */ 00850 int reference_count_; 00851 00852 /// The allocator use to destroy ourselves. 00853 ACE_Allocator *data_block_allocator_; 00854 00855 private: 00856 // = Disallow these operations. 00857 ACE_Data_Block &operator= (const ACE_Data_Block &); 00858 ACE_Data_Block (const ACE_Data_Block &); 00859 }; 00860 00861 ACE_END_VERSIONED_NAMESPACE_DECL 00862 00863 #if defined (__ACE_INLINE__) 00864 #include "ace/Message_Block.inl" 00865 #endif /* __ACE_INLINE__ */ 00866 00867 #include "ace/Message_Block_T.h" 00868 00869 #include /**/ "ace/post.h" 00870 00871 #endif /* ACE_MESSAGE_BLOCK_H */