00001 // -*- C++ -*- 00002 00003 //============================================================================= 00004 /** 00005 * @file Queued_Message.h 00006 * 00007 * $Id: Queued_Message.h 80306 2007-12-18 12:10:07Z johnnyw $ 00008 * 00009 * @author Carlos O'Ryan <coryan@uci.edu> 00010 */ 00011 //============================================================================= 00012 00013 #ifndef TAO_QUEUED_MESSAGE_H 00014 #define TAO_QUEUED_MESSAGE_H 00015 00016 #include /**/ "ace/pre.h" 00017 00018 #include "tao/LF_Invocation_Event.h" 00019 #include "ace/os_include/os_stddef.h" 00020 00021 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00022 # pragma once 00023 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00024 00025 struct iovec; 00026 00027 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00028 class ACE_Message_Block; 00029 class ACE_Allocator; 00030 class ACE_Time_Value; 00031 ACE_END_VERSIONED_NAMESPACE_DECL 00032 00033 TAO_BEGIN_VERSIONED_NAMESPACE_DECL 00034 00035 class TAO_ORB_Core; 00036 00037 /** 00038 * @class TAO_Queued_Message 00039 * 00040 * @brief Represent messages queued in the outgoing data path of the 00041 * TAO_Transport class. 00042 * 00043 * Please read the documentation in the TAO_Transport class to find 00044 * out more about the design of the outgoing data path. 00045 * 00046 * In some configurations TAO needs to maintain a per-connection queue 00047 * of outgoing messages. This queue is drained by the pluggable 00048 * protocols framework, normally under control of the ACE_Reactor, but 00049 * other configurations are conceivable. The elements in the queue 00050 * may be removed early, for example, because the application can 00051 * specify timeouts for each message, or because the underlying 00052 * connection is broken. 00053 * 00054 * In many cases the message corresponds to some application request, 00055 * the application may be blocked waiting for the request to be sent, 00056 * even more importantlyl, the ORB can be configured to use the 00057 * Leader/Followers strategy, in which case one of the waiting threads 00058 * can be required to wake up before its message completes 00059 * each message may contain a 'Sent_Notifier' 00060 * 00061 * <H4>NOTE:</H4> The contents of the ACE_Message_Block may have been 00062 * allocated from TSS storage, in that case we cannot steal them. 00063 * However, we do not need to perform a deep copy all the time, for 00064 * example, in a twoway request the sending thread blocks until the 00065 * data goes out. The queued message can borrow the memory as it will 00066 * be deallocated by the sending thread when it finishes. 00067 * Oneways and asynchronous calls are another story. 00068 * 00069 * @todo Change the ORB to allocate oneway and AMI buffer from global 00070 * memory, to avoid the data copy in this path. What happens 00071 * if the there is no queueing? Can we check that before 00072 * allocating the memory? 00073 * 00074 */ 00075 class TAO_Export TAO_Queued_Message : public TAO_LF_Invocation_Event 00076 { 00077 public: 00078 /// Constructor 00079 TAO_Queued_Message (TAO_ORB_Core *oc, 00080 ACE_Allocator *alloc = 0, 00081 bool is_heap_allocated = false); 00082 00083 /// Destructor 00084 virtual ~TAO_Queued_Message (void); 00085 00086 /** @name Intrusive list manipulation 00087 * 00088 * The messages are put in a doubled linked list (for easy insertion 00089 * and removal). To minimize memory allocations the list is 00090 * intrusive, i.e. each element in the list contains the pointers 00091 * for the next and previous element. 00092 * 00093 * The following methods are used to manipulate this implicit list. 00094 * 00095 * @todo We should implement this as a base template, something 00096 * like:<BR> 00097 * template<class T> Intrusive_Node {<BR> 00098 * public:<BR><BR> 00099 * void next (T *);<BR> 00100 * T* next () const;<BR><BR> 00101 * private:<BR> 00102 * T* next_;<BR> 00103 * };<BR> 00104 * and use it as follows:<BR> 00105 * class TAO_Queued_Message : public Intrusive_Node<TAO_Queued_Message><BR> 00106 * {<BR> 00107 * };<BR> 00108 * 00109 */ 00110 //@{ 00111 /// Set/get the next element in the list 00112 TAO_Queued_Message *next (void) const; 00113 00114 /// Set/get the previous element in the list 00115 TAO_Queued_Message *prev (void) const; 00116 00117 /// Remove this element from the list 00118 void remove_from_list (TAO_Queued_Message *&head, 00119 TAO_Queued_Message *&tail); 00120 00121 /// Insert the current element at the tail of the queue. 00122 void push_back (TAO_Queued_Message *&head, 00123 TAO_Queued_Message *&tail); 00124 00125 /// Insert the current element at the head of the queue. 00126 void push_front (TAO_Queued_Message *&head, 00127 TAO_Queued_Message *&tail); 00128 //@} 00129 00130 /** @name Template Methods 00131 */ 00132 //@{ 00133 00134 /// Return the length of the message 00135 /** 00136 * If the message has been partially sent it returns the number of 00137 * bytes that are still not sent. 00138 */ 00139 virtual size_t message_length (void) const = 0; 00140 00141 /// Return 1 if all the data has been sent 00142 virtual int all_data_sent (void) const = 0; 00143 00144 /// Fill up an io vector using the connects of the message 00145 /** 00146 * Different versions of this class represent the message using 00147 * either a single buffer, or a message block. 00148 * This method allows a derived class to fill up the contents of an 00149 * io vector, the TAO_Transport class uses this method to group as 00150 * many messages as possible in an iovector before sending them to 00151 * the OS I/O subsystem. 00152 * 00153 * @param iovcnt_max The number of elements in iov 00154 * @param iovcnt The number of elements already used by iov, this 00155 * method should update this counter 00156 * @param iov The io vector 00157 */ 00158 virtual void fill_iov (int iovcnt_max, 00159 int &iovcnt, 00160 iovec iov[]) const = 0; 00161 00162 /// Update the internal state, data has been sent. 00163 /** 00164 * After the TAO_Transport class completes a successful (or 00165 * partially successful) I/O operation it must update the state of 00166 * all the messages queued. This callback method is used by each 00167 * message to update its state and determine if all the data has 00168 * been sent already. 00169 * 00170 * @param byte_count The number of bytes succesfully sent. The 00171 * TAO_Queued_Message should decrement this value 00172 * by the number of bytes that must still be sent. 00173 * @return Returns 1 if the TAO_Queued_Message has any more data to 00174 * send. 00175 */ 00176 virtual void bytes_transferred (size_t &byte_count) = 0; 00177 00178 /// Clone this element 00179 /* 00180 * Clone the element and return a pointer to the cloned element on 00181 * the heap. 00182 * 00183 * @param allocator Use the allocator for creating the new element 00184 * on the heap. Remember, that the allocator will 00185 * not be used allocate the data contained in this 00186 * element. 00187 */ 00188 virtual TAO_Queued_Message *clone (ACE_Allocator *allocator) = 0; 00189 00190 /// Reclaim resources 00191 /** 00192 * Reliable messages are allocated from the stack, thus they do not 00193 * be deallocated. 00194 * Asynchronous (SYNC_NONE) messages are allocated from the heap (or 00195 * a pool), they need to be reclaimed explicitly. 00196 */ 00197 virtual void destroy (void) = 0; 00198 00199 /// Check for timeout 00200 /** 00201 * @param now Pass in the current time using 00202 * ACE_High_Res_Timer::gettimeofday_hr(). 00203 * This is a parameter in order to avoid calling gettimeofday_hr() inside 00204 * of this method (which will be called in a tight loop). 00205 * @return true if the relative roundtrip timeout has expired. 00206 */ 00207 virtual bool is_expired (const ACE_Time_Value &now) const; 00208 //@} 00209 00210 protected: 00211 /* 00212 * Allocator that was used to create @c this object on the heap. If the 00213 * allocator is null then @a this is on stack. 00214 */ 00215 ACE_Allocator *allocator_; 00216 00217 /* 00218 * A flag to indicate whether @a this is on stack or heap. A true value 00219 * indicates that @a this was created on heap. 00220 */ 00221 bool const is_heap_created_; 00222 00223 /// Cached copy of ORB_Core pointer 00224 TAO_ORB_Core *orb_core_; 00225 00226 private: 00227 /// Implement an intrusive double-linked list for the message queue 00228 TAO_Queued_Message *next_; 00229 TAO_Queued_Message *prev_; 00230 }; 00231 00232 TAO_END_VERSIONED_NAMESPACE_DECL 00233 00234 #if defined (__ACE_INLINE__) 00235 # include "tao/Queued_Message.inl" 00236 #endif /* __ACE_INLINE__ */ 00237 00238 00239 #include /**/ "ace/post.h" 00240 00241 #endif /* TAO_QUEUED_MESSAGE_H */