Queued_Message.h

Go to the documentation of this file.
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 */

Generated on Tue Feb 2 17:37:52 2010 for TAO by  doxygen 1.4.7