3 // =========================================================================
5 * @file AMH_Response_Handler.h
7 * @author Mayur Deshpande <mayur@ics.uci.edu>
9 // =========================================================================
11 #ifndef TAO_AMH_RESPONSE_HANDLER_H
12 #define TAO_AMH_RESPONSE_HANDLER_H
14 #include "tao/Messaging/messaging_export.h"
16 #include "tao/Allocator.h"
17 #include "tao/Service_Context.h"
19 #include "tao/LocalObject.h"
20 #include "tao/Buffer_Allocator_T.h"
21 #include "tao/GIOPC.h"
22 #include "ace/Synch_Traits.h"
23 #include "ace/Thread_Mutex.h"
24 #include "ace/Null_Mutex.h"
25 #include "tao/Exception.h"
27 #if !defined (ACE_LACKS_PRAGMA_ONCE)
29 #endif /* ACE_LACKS_PRAGMA_ONCE */
31 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
33 ACE_END_VERSIONED_NAMESPACE_DECL
35 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
38 class TAO_GIOP_Message_Base
;
41 class TAO_ServerRequest
;
43 typedef ACE_Allocator TAO_AMH_BUFFER_ALLOCATOR
;
46 * @class TAO_AMH_Response_Handler
48 * @brief Class representing an Asynchronous-Method-Handling (AMH)
49 * ResponseHandler (RH) object.
51 * Class encapsulates state required to send a response back to the
52 * client independent of the thread that originally created the state
53 * on the activation-record. Thus the required state (copied from
54 * TAO_Server_Request) is 'stored' on the heap.
56 * One RH is created for every client request and the RH can be used
57 * only once i.e., the asynchronous method can be called only once.
58 * This class also encapsulates various initialization and
59 * response-sending functionality that is common to all RHs (generated
60 * by the IDL compiler). Thus the IDL-compiler has to generate less
61 * code which in turn reduces the overall code size for an
64 class TAO_Messaging_Export TAO_AMH_Response_Handler
65 : public virtual ::CORBA::LocalObject
69 TAO_AMH_Response_Handler ();
73 * Releases the transport and in case of an error, sends the appropriate
74 * exception back to the client
76 virtual ~TAO_AMH_Response_Handler ();
79 * Stores necessary information from a TAO_Server_Request onto the heap
81 virtual void init (TAO_ServerRequest
&server_request
,
82 TAO_AMH_BUFFER_ALLOCATOR
* allocator
);
84 /// @name Mutators for refcount
86 virtual void _remove_ref ();
90 /// Sets up the various parameters in anticipation of returning a reply
91 /// to the client. return/OUT/INOUT arguments are marshalled into the
92 /// Output stream after this method has been called.
93 void _tao_rh_init_reply ();
95 /// Sends the marshalled reply back to the client.
96 void _tao_rh_send_reply ();
98 /// Send back an exception to the client.
99 void _tao_rh_send_exception (const CORBA::Exception
&ex
);
101 /// Send back a location forward exception to the client.
102 void _tao_rh_send_location_forward (CORBA::Object_ptr fwd
,
103 CORBA::Boolean is_perm
);
106 /// The outgoing CDR stream
108 * The IDL-generated ResponseHandler implementations used this field
109 * to marshal the response.
110 * Making it a field instead of a public accessor makes the code in
111 * the generated ResponseHandler implementation a lot more readable.
113 TAO_OutputCDR _tao_out
;
115 /// Reply status (will be NO_EXCEPTION in the majority of the
116 GIOP::ReplyStatusType reply_status_
;
119 TAO_AMH_Response_Handler (const TAO_AMH_Response_Handler
&) = delete;
120 TAO_AMH_Response_Handler
& operator= (const TAO_AMH_Response_Handler
&) = delete;
122 /// Pointer to the original message-base
123 TAO_GIOP_Message_Base
*mesg_base_
;
125 /// Copy of the request-id of the original Server-Request
126 CORBA::ULong request_id_
;
128 CORBA::Boolean response_expected_
;
130 /// Handle to transport through which the reply will be sent
131 /// Copy of transport in original Server_Request
132 TAO_Transport
*transport_
;
134 /// A pointer to the ORB Core for the context where the request was
136 TAO_ORB_Core
* orb_core_
;
138 /// The reply service context
139 TAO_Service_Context reply_service_context_
;
141 /// Alwyas set to true (we always have something to return to the
143 // @@ Mayur: I think not! This is used to generate padding in GIOP
144 // 1.2 messages (where the payload must start on an 8-byte
145 // boundary. But some replys have no payload (only header), in
146 // those cases you cannot insert the padding. We need the
147 // ResponseHandler to set this field correctly!
148 CORBA::Boolean argument_flag_
;
151 * Various states the ResponseHandler can be in.
153 * These states represent various states the RH can be in and
154 * the states are used not only in implementing the 'once-only semantics of
155 * RHs, but in making sure well the call thread-safe as well.
159 TAO_RS_UNINITIALIZED
,
164 RH_Reply_Status rh_reply_status_
;
166 // I would use the "state pattern"..
167 // Carlos, Isn't that an overkill?
168 // @@ Mayur: it depends on what form of the "State Pattern" you
169 // use. The more generic form, as described in GoF, uses a class
170 // for each state, super-elegant but indeed a bit heavy handed.
171 // The lighter-weight form (using a state variable
173 /// Mutex to ensure the AMH-RH method call is thread-safe.
174 TAO_SYNCH_MUTEX mutex_
;
176 /// Allocator used to allocate this object. If zero then we are allocated
178 TAO_AMH_BUFFER_ALLOCATOR
* allocator_
;
184 * @class ARH_Refcount_Functor
186 * @brief Functor for refcounting of TAO_AMH_Response_Handler
188 * This is used to safely handle the destruction of
189 * TAO_AMH_Response_Handler objects which are created on the
190 * heap. We cannot use auto_ptr <> since it calls delete on the
191 * pointer, and calling delete on TAO_AMH_Response_Handler *
192 * will not work. Hence this functor will be used with Auto_Functor
193 * class to handle the memory safely.
195 * @todo Ideally, this class can be a generic class. But that
196 * requires quite a bit of cleanup within TAO to be more useful.
198 class TAO_Messaging_Export ARH_Refcount_Functor
201 void operator() (TAO_AMH_Response_Handler
*arh
) noexcept
;
205 TAO_END_VERSIONED_NAMESPACE_DECL
207 #endif /* TAO_AMH_RESPONSE_HANDLER_H */