Major cleanup in PortableServer library
[ACE_TAO.git] / TAO / tao / PortableServer / Servant_Upcall.cpp
blobae36b5d74862ec5bfab7ccf189fa15739cddd90d
1 #include "tao/PortableServer/Object_Adapter.h"
2 #include "tao/PortableServer/Servant_Upcall.h"
3 #include "tao/PortableServer/Root_POA.h"
4 #include "tao/PortableServer/Default_Servant_Dispatcher.h"
5 #include "tao/PortableServer/Collocated_Object_Proxy_Broker.h"
6 #include "tao/PortableServer/Active_Object_Map_Entry.h"
7 #include "tao/PortableServer/ForwardRequestC.h"
9 // -- TAO Include --
10 #include "tao/ORB.h"
11 #include "tao/ORB_Core.h"
12 #include "tao/debug.h"
14 #if !defined (__ACE_INLINE__)
15 # include "tao/PortableServer/Servant_Upcall.inl"
16 #endif /* __ACE_INLINE__ */
18 #include "ace/OS_NS_string.h"
20 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
22 namespace TAO
24 namespace Portable_Server
26 Servant_Upcall::Servant_Upcall (TAO_ORB_Core *oc)
27 : object_adapter_ (0),
28 poa_ (0),
29 servant_ (0),
30 state_ (INITIAL_STAGE),
31 system_id_ (TAO_POA_OBJECT_ID_BUF_SIZE, 0, system_id_buf_),
32 user_id_ (0),
33 current_context_ (),
34 #if (TAO_HAS_MINIMUM_POA == 0)
35 cookie_ (0),
36 operation_ (0),
37 #endif /* TAO_HAS_MINIMUM_POA == 0 */
38 active_object_map_entry_ (0)
40 TAO_Object_Adapter *object_adapter =
41 dynamic_cast<TAO_Object_Adapter *>(oc->poa_adapter ());
42 this->object_adapter_ = object_adapter;
45 int
46 Servant_Upcall::prepare_for_upcall (
47 const TAO::ObjectKey &key,
48 const char *operation,
49 CORBA::Object_out forward_to)
51 while (1)
53 bool wait_occurred_restart_call = false;
55 int const result =
56 this->prepare_for_upcall_i (key,
57 operation,
58 forward_to,
59 wait_occurred_restart_call);
61 if (result == TAO_Adapter::DS_FAILED &&
62 wait_occurred_restart_call)
64 // We ended up waiting on a condition variable. The POA
65 // state may have changed while we are waiting. Therefore,
66 // we need to call prepare_for_upcall_i() again. We also
67 // need to cleanup the state of the upcall object before
68 // continuing.
69 this->upcall_cleanup ();
70 continue;
72 else
74 return result;
79 int
80 Servant_Upcall::prepare_for_upcall_i (
81 const TAO::ObjectKey &key,
82 const char *operation,
83 CORBA::Object_out forward_to,
84 bool &wait_occurred_restart_call)
86 // Acquire the object adapter lock first.
87 int result = this->object_adapter_->lock ().acquire ();
88 if (result == -1)
89 // Locking error.
90 throw ::CORBA::OBJ_ADAPTER ();
92 // We have acquired the object adapter lock. Record this for later
93 // use.
94 this->state_ = OBJECT_ADAPTER_LOCK_ACQUIRED;
96 // Check if a non-servant upcall is in progress. If a non-servant
97 // upcall is in progress, wait for it to complete. Unless of
98 // course, the thread making the non-servant upcall is this thread.
99 this->object_adapter_->wait_for_non_servant_upcalls_to_complete ();
101 // Locate the POA.
102 this->object_adapter_->locate_poa (key, this->system_id_, this->poa_);
104 // Check the state of the POA.
105 this->poa_->check_state ();
107 // Setup current for this request.
108 this->current_context_.setup (this->poa_, key);
110 // Increase <poa->outstanding_requests_> for the duration of finding
111 // the POA, finding the servant, and making the upcall.
112 this->poa_->increment_outstanding_requests ();
114 // We have setup the POA Current. Record this for later use.
115 this->state_ = POA_CURRENT_SETUP;
117 #if (TAO_HAS_MINIMUM_CORBA == 0) && !defined (CORBA_E_COMPACT) && !defined (CORBA_E_MICRO)
120 #endif /* TAO_HAS_MINIMUM_CORBA */
121 // Lookup the servant.
122 this->servant_ =
123 this->poa_->locate_servant_i (operation,
124 this->system_id_,
125 *this,
126 this->current_context_,
127 wait_occurred_restart_call);
129 if (wait_occurred_restart_call)
130 return TAO_Adapter::DS_FAILED;
131 #if (TAO_HAS_MINIMUM_CORBA == 0) && !defined (CORBA_E_COMPACT) && !defined (CORBA_E_MICRO)
133 catch (const ::PortableServer::ForwardRequest& forward_request)
135 forward_to =
136 CORBA::Object::_duplicate (forward_request.forward_reference.in ());
137 return TAO_Adapter::DS_FORWARD;
139 #else
140 ACE_UNUSED_ARG (forward_to);
141 #endif /* TAO_HAS_MINIMUM_CORBA */
143 // Now that we know the servant.
144 this->current_context_.servant (this->servant_);
146 // For servants from Servant Locators, there is no active object map
147 // entry.
148 if (this->active_object_map_entry ())
149 this->current_context_.priority (this->active_object_map_entry ()->priority_);
151 if (this->state_ != OBJECT_ADAPTER_LOCK_RELEASED)
153 // Release the object adapter lock.
154 this->object_adapter_->lock ().release ();
156 // We have release the object adapter lock. Record this for
157 // later use.
158 this->state_ = OBJECT_ADAPTER_LOCK_RELEASED;
161 // Serialize servants (if appropriate).
162 this->single_threaded_poa_setup ();
164 // We have acquired the servant lock. Record this for later use.
165 this->state_ = SERVANT_LOCK_ACQUIRED;
167 // After this point, <this->servant_> is ready for dispatching.
168 return TAO_Adapter::DS_OK;
171 void
172 Servant_Upcall::pre_invoke_remote_request (TAO_ServerRequest &req)
174 this->object_adapter_->servant_dispatcher_->pre_invoke_remote_request (
175 this->poa (),
176 this->priority (),
177 req,
178 this->pre_invoke_state_);
181 void
182 Servant_Upcall::pre_invoke_collocated_request ()
184 this->object_adapter_->servant_dispatcher_->pre_invoke_collocated_request (
185 this->poa (),
186 this->priority (),
187 this->pre_invoke_state_);
190 void
191 Servant_Upcall::post_invoke ()
193 this->object_adapter_->servant_dispatcher_->post_invoke (
194 this->poa (),
195 this->pre_invoke_state_);
198 Servant_Upcall::Pre_Invoke_State::Pre_Invoke_State ()
199 : state_ (NO_ACTION_REQUIRED),
200 original_native_priority_ (0),
201 original_CORBA_priority_ (0)
205 ::TAO_Root_POA *
206 Servant_Upcall::lookup_POA (const TAO::ObjectKey &key)
208 // Acquire the object adapter lock first.
209 if (this->object_adapter_->lock ().acquire () == -1)
210 // Locking error.
211 throw ::CORBA::OBJ_ADAPTER ();
213 // We have acquired the object adapter lock. Record this for later
214 // use.
215 this->state_ = OBJECT_ADAPTER_LOCK_ACQUIRED;
217 // Check if a non-servant upcall is in progress. If a non-servant
218 // upcall is in progress, wait for it to complete. Unless of
219 // course, the thread making the non-servant upcall is this thread.
220 this->object_adapter_->wait_for_non_servant_upcalls_to_complete ();
222 // Locate the POA.
223 this->object_adapter_->locate_poa (key, this->system_id_, this->poa_);
225 return this->poa_;
228 Servant_Upcall::~Servant_Upcall ()
230 this->upcall_cleanup ();
233 void
234 Servant_Upcall::upcall_cleanup ()
236 this->post_invoke ();
238 switch (this->state_)
240 case SERVANT_LOCK_ACQUIRED:
241 // Unlock servant (if appropriate).
242 this->single_threaded_poa_cleanup ();
244 ACE_FALLTHROUGH;
246 case OBJECT_ADAPTER_LOCK_RELEASED:
247 // Cleanup servant locator related state. Note that because
248 // this operation does not change any Object Adapter related
249 // state, it is ok to call it outside the lock.
250 this->post_invoke_servant_cleanup ();
252 // Since the object adapter lock was released, we must acquire
253 // it.
255 // Note that errors are ignored here since we cannot do much
256 // with it.
257 this->object_adapter_->lock ().acquire ();
259 // Check if a non-servant upcall is in progress. If a
260 // non-servant upcall is in progress, wait for it to complete.
261 // Unless of course, the thread making the non-servant upcall is
262 // this thread.
263 this->object_adapter_->wait_for_non_servant_upcalls_to_complete_no_throw ();
265 // Cleanup servant related state.
266 this->servant_cleanup ();
268 ACE_FALLTHROUGH;
270 case POA_CURRENT_SETUP:
271 // Cleanup POA related state.
272 this->poa_cleanup ();
274 // Teardown current for this request.
275 this->current_context_.teardown ();
277 ACE_FALLTHROUGH;
279 case OBJECT_ADAPTER_LOCK_ACQUIRED:
280 // Finally, since the object adapter lock was acquired, we must
281 // release it.
282 this->object_adapter_->lock ().release ();
284 ACE_FALLTHROUGH;
286 case INITIAL_STAGE:
287 default:
288 // @@ Keep compiler happy, the states above are the only
289 // possible ones.
290 break;
294 void
295 Servant_Upcall::post_invoke_servant_cleanup ()
297 this->poa_->post_invoke_servant_cleanup (this->current_context_.object_id (),
298 *this);
301 void
302 Servant_Upcall::single_threaded_poa_setup ()
304 #if (TAO_HAS_MINIMUM_POA == 0)
305 // Serialize servants (if necessary).
307 // Note that this lock must be acquired *after* the object adapter
308 // lock has been released. This is necessary since we cannot block
309 // waiting for the servant lock while holding the object adapter
310 // lock. Otherwise, the thread that wants to release this lock will
311 // not be able to do so since it can't acquire the object adapterx
312 // lock.
313 if (this->poa_->enter() == -1)
314 // Locking error.
315 throw ::CORBA::OBJ_ADAPTER ();
316 #endif /* !TAO_HAS_MINIMUM_POA == 0 */
319 void
320 Servant_Upcall::single_threaded_poa_cleanup ()
322 #if (TAO_HAS_MINIMUM_POA == 0)
323 // Since the servant lock was acquired, we must release it.
324 int const result = this->poa_->exit ();
326 ACE_UNUSED_ARG (result);
327 #endif /* TAO_HAS_MINIMUM_POA == 0 */
330 void
331 Servant_Upcall::increment_servant_refcount ()
333 // Cleanup servant related stuff.
334 if (this->active_object_map_entry_ != 0)
335 ++this->active_object_map_entry_->reference_count_;
338 void
339 Servant_Upcall::servant_cleanup ()
341 // Cleanup servant related stuff.
342 if (this->active_object_map_entry_ != 0)
344 // Decrement the reference count.
345 CORBA::UShort const new_count =
346 --this->active_object_map_entry_->reference_count_;
348 if (new_count == 0)
352 this->poa_->cleanup_servant (
353 this->active_object_map_entry_->servant_,
354 this->active_object_map_entry_->user_id_);
356 catch (...)
358 // Ignore errors from servant cleanup ....
361 if (this->poa_->waiting_servant_deactivation() > 0)
363 // Wakeup all waiting threads.
364 this->poa_->servant_deactivation_condition_.broadcast ();
370 void
371 Servant_Upcall::poa_cleanup ()
373 // Decrease <poa->outstanding_requests_> now that the upcall
374 // is complete.
376 // Note that the object adapter lock is acquired before
377 // <POA::outstanding_requests_> is decreased.
378 CORBA::ULong outstanding_requests =
379 this->poa_->decrement_outstanding_requests ();
381 // Check if all pending requests are over.
382 if (outstanding_requests == 0)
384 // If locking is enabled and some thread is waiting in POA::destroy.
385 if (this->poa_->wait_for_completion_pending_)
387 // Wakeup all waiting threads.
388 this->poa_->outstanding_requests_condition_.broadcast ();
391 // Note that there is no need to check for
392 // <non_servant_upcall_in_progress> since it is not possible for
393 // non-servant upcalls to be in progress at this point.
394 if (this->poa_->waiting_destruction_)
398 this->poa_->complete_destruction_i ();
400 catch (const ::CORBA::Exception& ex)
402 // Ignore exceptions
403 ex._tao_print_exception ("TAO_POA::~complete_destruction_i");
406 this->poa_ = nullptr;
413 TAO_END_VERSIONED_NAMESPACE_DECL