Revert "Use a variable on the stack to not have a temporary in the call"
[ACE_TAO.git] / TAO / tao / Messaging / Asynch_Invocation.cpp
blob5a94b7bf591fe6ff92afcbedf872b79eb734e097
1 // -*- C++ -*-
2 #include "tao/Messaging/Asynch_Invocation.h"
3 #include "tao/Messaging/Asynch_Reply_Dispatcher.h"
5 #include "tao/Profile_Transport_Resolver.h"
6 #include "tao/Invocation_Utils.h"
7 #include "tao/operation_details.h"
8 #include "tao/Bind_Dispatcher_Guard.h"
9 #include "tao/Transport.h"
10 #include "tao/Muxed_TMS.h"
11 #include "tao/GIOP_Message_Base.h"
12 #include "tao/ORB_Constants.h"
14 #if TAO_HAS_INTERCEPTORS == 1
15 # include "tao/PortableInterceptorC.h"
16 #endif /*TAO_HAS_INTERCEPTORS */
18 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
20 namespace TAO
22 Asynch_Remote_Invocation::Asynch_Remote_Invocation (
23 CORBA::Object_ptr otarget,
24 Profile_Transport_Resolver &resolver,
25 TAO_Operation_Details &detail,
26 TAO_Asynch_Reply_Dispatcher_Base *rd,
27 bool response_expected)
28 : Synch_Twoway_Invocation (otarget,
29 resolver,
30 detail,
31 response_expected)
32 , safe_rd_ (rd)
36 Invocation_Status
37 Asynch_Remote_Invocation::remote_invocation (ACE_Time_Value *max_wait_time)
39 Invocation_Status s = TAO_INVOKE_FAILURE;
41 #if TAO_HAS_INTERCEPTORS == 1
42 s = this->send_request_interception ();
44 if (s != TAO_INVOKE_SUCCESS)
45 return s;
47 // We have started the interception flow. We need to call the
48 // ending interception flow if things go wrong. The purpose of the
49 // try block is to take care of the cases when things go wrong.
50 try
52 #endif /* TAO_HAS_INTERCEPTORS */
53 TAO_Transport* const transport = this->resolver_.transport ();
55 if (!transport)
57 // Way back, we failed to find a profile we could connect to.
58 // We've come this far only so we reach the interception points
59 // in case they can fix things. Time to bail....
60 throw CORBA::TRANSIENT (CORBA::OMGVMCID | 2, CORBA::COMPLETED_NO);
63 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ace_mon,
64 transport->output_cdr_lock (), TAO_INVOKE_FAILURE);
66 TAO_OutputCDR & cdr =
67 this->resolver_.transport ()->out_stream ();
70 CDR_Byte_Order_Guard cdr_guard (cdr, this->_tao_byte_order ());
72 // Oneway semantics. See comments for below send_message()
73 // call.
74 cdr.message_attributes (this->details_.request_id (),
75 this->resolver_.stub (),
76 TAO_Message_Semantics (TAO_Message_Semantics::TAO_ONEWAY_REQUEST,
77 TAO_Message_Semantics::TAO_ASYNCH_CALLBACK),
78 max_wait_time);
80 this->write_header (cdr);
82 this->marshal_data (cdr);
84 // Register a reply dispatcher for this invocation. Use the
85 // preallocated reply dispatcher.
86 TAO_Bind_Dispatcher_Guard dispatch_guard (
87 this->details_.request_id (),
88 this->safe_rd_.get (),
89 transport->tms ());
91 // Now that we have bound the reply dispatcher to the map, just
92 // loose ownership of the reply dispatcher.
93 this->safe_rd_.release ();
95 if (dispatch_guard.status () != 0)
97 // @@ What is the right way to handle this error? Do we need
98 // to call the interceptors in this case?
99 throw ::CORBA::INTERNAL (TAO::VMCID, CORBA::COMPLETED_NO);
102 // Do not unbind during destruction. We need the entry to be
103 // there in the map since the reply dispatcher depends on
104 // that. This is also a trigger to loose the ownership of the
105 // reply dispatcher.
106 dispatch_guard.status (TAO_Bind_Dispatcher_Guard::NO_UNBIND);
108 // Send it as a oneway request. It will make all the required
109 // paraphernalia within the ORB to fire, like buffering if
110 // send blocks etc.
111 s = this->send_message (cdr,
112 TAO_Message_Semantics (TAO_Message_Semantics::TAO_ONEWAY_REQUEST,
113 TAO_Message_Semantics::TAO_ASYNCH_CALLBACK),
114 max_wait_time);
115 } // CDR_Byte_Order_Guard
117 ace_mon.release();
119 #if TAO_HAS_INTERCEPTORS == 1
120 // NOTE: We don't need to do the auto_ptr <> trick. We got here
121 // in the first place since the message was sent properly,
122 // which implies a reply would be available. Therefore the
123 // reply dispatcher should be available for another thread to
124 // collect and dispatch the reply. In MT cases, things are
125 // more hairy. Just imagine what happens when another thread
126 // is collecting the reply when we are happily invoking
127 // interceptors?
129 // Nothing great on here. If we get a restart during send or a
130 // proper send, we are supposed to call receiver_other ()
131 // interception point. So we do that here
132 Invocation_Status const tmp = this->receive_other_interception ();
134 // We got an error during the interception.
135 if (s == TAO_INVOKE_SUCCESS && tmp != TAO_INVOKE_SUCCESS)
136 s = tmp;
137 #endif /* TAO_HAS_INTERCEPTORS */
139 // If an error occurred just return. At this point all the
140 // endpoint interception would have been invoked. The callee
141 // would take care of the rest.
142 if (s != TAO_INVOKE_SUCCESS)
143 return s;
145 // transport strategy takes care of idling transport or not
146 transport->idle_after_send ();
147 // release transport from resolver in any case since we don't
148 // want the resolver to make the transport idle if the strategy
149 // told it not to
150 this->resolver_.transport_released ();
152 #if TAO_HAS_INTERCEPTORS == 1
154 catch ( ::CORBA::Exception& ex)
156 PortableInterceptor::ReplyStatus const status =
157 this->handle_any_exception (&ex);
159 if (status == PortableInterceptor::LOCATION_FORWARD ||
160 status == PortableInterceptor::TRANSPORT_RETRY)
161 s = TAO_INVOKE_RESTART;
162 else if (status == PortableInterceptor::SYSTEM_EXCEPTION
163 || status == PortableInterceptor::USER_EXCEPTION)
164 throw;
166 catch (...)
168 // Notify interceptors of non-CORBA exception, and propagate
169 // that exception to the caller.
171 PortableInterceptor::ReplyStatus const st =
172 this->handle_all_exception ();
174 if (st == PortableInterceptor::LOCATION_FORWARD ||
175 st == PortableInterceptor::TRANSPORT_RETRY)
176 s = TAO_INVOKE_RESTART;
177 else
178 throw;
180 #endif /* TAO_HAS_INTERCEPTORS */
182 return s;
186 TAO_END_VERSIONED_NAMESPACE_DECL