Revert "Use a variable on the stack to not have a temporary in the call"
[ACE_TAO.git] / TAO / tao / Queued_Message.h
blob037c3a1ca0ef34faa67cc4bbe0eabc9c9f72293a
1 // -*- C++ -*-
3 //=============================================================================
4 /**
5 * @file Queued_Message.h
7 * @author Carlos O'Ryan <coryan@uci.edu>
8 */
9 //=============================================================================
11 #ifndef TAO_QUEUED_MESSAGE_H
12 #define TAO_QUEUED_MESSAGE_H
14 #include /**/ "ace/pre.h"
16 #include "tao/LF_Invocation_Event.h"
17 #include "ace/os_include/os_stddef.h"
19 #if !defined (ACE_LACKS_PRAGMA_ONCE)
20 # pragma once
21 #endif /* ACE_LACKS_PRAGMA_ONCE */
23 struct iovec;
25 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
26 class ACE_Message_Block;
27 class ACE_Allocator;
28 class ACE_Time_Value;
29 ACE_END_VERSIONED_NAMESPACE_DECL
31 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
33 class TAO_ORB_Core;
35 /**
36 * @class TAO_Queued_Message
38 * @brief Represent messages queued in the outgoing data path of the
39 * TAO_Transport class.
41 * Please read the documentation in the TAO_Transport class to find
42 * out more about the design of the outgoing data path.
44 * In some configurations TAO needs to maintain a per-connection queue
45 * of outgoing messages. This queue is drained by the pluggable
46 * protocols framework, normally under control of the ACE_Reactor, but
47 * other configurations are conceivable. The elements in the queue
48 * may be removed early, for example, because the application can
49 * specify timeouts for each message, or because the underlying
50 * connection is broken.
52 * In many cases the message corresponds to some application request,
53 * the application may be blocked waiting for the request to be sent,
54 * even more importantly, the ORB can be configured to use the
55 * Leader/Followers strategy, in which case one of the waiting threads
56 * can be required to wake up before its message completes.
57 * Each message may contain a 'Sent_Notifier'
59 * <H4>NOTE:</H4> The contents of the ACE_Message_Block may have been
60 * allocated from TSS storage, in that case we cannot steal them.
61 * However, we do not need to perform a deep copy all the time, for
62 * example, in a twoway request the sending thread blocks until the
63 * data goes out. The queued message can borrow the memory as it will
64 * be deallocated by the sending thread when it finishes.
65 * Oneways and asynchronous calls are another story.
67 * @todo Change the ORB to allocate oneway and AMI buffer from global
68 * memory, to avoid the data copy in this path. What happens
69 * if the there is no queueing? Can we check that before
70 * allocating the memory?
72 class TAO_Export TAO_Queued_Message : public TAO_LF_Invocation_Event
74 public:
75 /// Constructor
76 TAO_Queued_Message (TAO_ORB_Core *oc,
77 ACE_Allocator *alloc = 0,
78 bool is_heap_allocated = false);
80 /// Destructor
81 virtual ~TAO_Queued_Message ();
83 /** @name Intrusive list manipulation
85 * The messages are put in a doubled linked list (for easy insertion
86 * and removal). To minimize memory allocations the list is
87 * intrusive, i.e. each element in the list contains the pointers
88 * for the next and previous element.
90 * The following methods are used to manipulate this implicit list.
92 * @todo We should implement this as a base template, something
93 * like:<BR>
94 * template<class T> Intrusive_Node {<BR>
95 * public:<BR><BR>
96 * void next (T *);<BR>
97 * T* next () const;<BR><BR>
98 * private:<BR>
99 * T* next_;<BR>
100 * };<BR>
101 * and use it as follows:<BR>
102 * class TAO_Queued_Message : public Intrusive_Node<TAO_Queued_Message><BR>
103 * {<BR>
104 * };<BR>
107 //@{
108 /// Set/get the next element in the list
109 TAO_Queued_Message *next () const;
111 /// Set/get the previous element in the list
112 TAO_Queued_Message *prev () const;
114 /// Remove this element from the list
115 void remove_from_list (TAO_Queued_Message *&head,
116 TAO_Queued_Message *&tail);
118 /// Insert the current element at the tail of the queue.
119 void push_back (TAO_Queued_Message *&head,
120 TAO_Queued_Message *&tail);
122 /// Insert the current element at the head of the queue.
123 void push_front (TAO_Queued_Message *&head,
124 TAO_Queued_Message *&tail);
125 //@}
127 /** @name Template Methods
129 //@{
130 /// Return the length of the message
132 * If the message has been partially sent it returns the number of
133 * bytes that are still not sent.
135 virtual size_t message_length () const = 0;
137 /// Return 1 if all the data has been sent
138 virtual int all_data_sent () const = 0;
140 /// Fill up an io vector using the connects of the message
142 * Different versions of this class represent the message using
143 * either a single buffer, or a message block.
144 * This method allows a derived class to fill up the contents of an
145 * io vector, the TAO_Transport class uses this method to group as
146 * many messages as possible in an iovector before sending them to
147 * the OS I/O subsystem.
149 * @param iovcnt_max The number of elements in iov
150 * @param iovcnt The number of elements already used by iov, this
151 * method should update this counter
152 * @param iov The io vector
154 virtual void fill_iov (int iovcnt_max,
155 int &iovcnt,
156 iovec iov[]) const = 0;
158 /// Update the internal state, data has been sent.
160 * After the TAO_Transport class completes a successful (or
161 * partially successful) I/O operation it must update the state of
162 * all the messages queued. This callback method is used by each
163 * message to update its state and determine if all the data has
164 * been sent already.
166 * @param byte_count The number of bytes successfully sent. The
167 * TAO_Queued_Message should decrement this value
168 * by the number of bytes that must still be sent.
169 * @return Returns 1 if the TAO_Queued_Message has any more data to
170 * send.
172 virtual void bytes_transferred (size_t &byte_count) = 0;
174 /// Clone this element
176 * Clone the element and return a pointer to the cloned element on
177 * the heap.
179 * @param allocator Use the allocator for creating the new element
180 * on the heap. Remember, that the allocator will
181 * not be used allocate the data contained in this
182 * element.
184 virtual TAO_Queued_Message *clone (ACE_Allocator *allocator) = 0;
186 /// Reclaim resources
188 * Reliable messages are allocated from the stack, thus they do not
189 * be deallocated.
190 * Asynchronous (SYNC_NONE) messages are allocated from the heap (or
191 * a pool), they need to be reclaimed explicitly.
193 virtual void destroy () = 0;
195 /// Check for timeout
197 * @param now Pass in the current time using
198 * ACE_High_Res_Timer::gettimeofday_hr().
199 * This is a parameter in order to avoid calling gettimeofday_hr() inside
200 * of this method (which will be called in a tight loop).
201 * @return true if the relative roundtrip timeout has expired.
203 virtual bool is_expired (const ACE_Time_Value &now) const;
205 /// Provide a hook for copying the underlying data
207 * @param chain For use in determining origin of underlying data.
208 * This parameter must not be modified (through const_cast).
210 virtual void copy_if_necessary (const ACE_Message_Block* chain) = 0;
211 //@}
213 protected:
215 * Allocator that was used to create @c this object on the heap. If the
216 * allocator is null then @a this is on stack.
218 ACE_Allocator *allocator_;
221 * A flag to indicate whether @a this is on stack or heap. A true value
222 * indicates that @a this was created on heap.
224 bool const is_heap_created_;
226 /// Cached copy of ORB_Core pointer
227 TAO_ORB_Core *orb_core_;
229 private:
230 /// Implement an intrusive double-linked list for the message queue
231 TAO_Queued_Message *next_;
232 TAO_Queued_Message *prev_;
235 TAO_END_VERSIONED_NAMESPACE_DECL
237 #if defined (__ACE_INLINE__)
238 # include "tao/Queued_Message.inl"
239 #endif /* __ACE_INLINE__ */
242 #include /**/ "ace/post.h"
244 #endif /* TAO_QUEUED_MESSAGE_H */