Re: [orbitcpp-list] Destroying CORBA objects
Status: Beta
Brought to you by:
philipd
From: Phil D. <ph...@us...> - 2000-10-26 20:09:14
|
Hi Sam, hi list, As discussed in an earlier mail on this thread, 'delete this' is a bad idea in a corba servant, since the orb has a reference to the object in the active object map. An additional barrier to doing a 'delete this' from within a corba method is that even if you remove the servant from the active object map first, the poa is at liberty to reference the servant on post-invoke. In order to overcome this, the C++ mapping provides a server side reference counting mechanism for servants, enabling a 'remove()' method to be implemented as an idl operation on the servant. (see section 1.36.1 and 1.36.2 of the C++ language mapping). Here's the receipe for implementing reference counted transient objects in CORBA (this now works with cvs version of orbitcpp): 1) Make the implementation inherit from the PortableServer::RefCountServantBase mixin base class. E.g. class TransientObj_impl : public virtual POA_test::TransientObj, public virtual PortableServer::RefCountServantBase{ ... }; This base class implements the _add_ref() and _remove_ref() methods on the PortableServer::ServantBase base class with an implementation which manages a thread-safe count, and calls 'delete this()' when it hits 0. 2) In your factory (or wherever the servant creation is done) you must be careful to call remove_ref() on your implementation once you've finished with it. E.g. test::TransientObj_ptr test_impl::TestFactory_impl::createTransientObj(){ test_impl::TransientObj_impl *impl = new test_impl::TransientObj_impl; test::TransientObj_ptr ptr = impl->_this(); // the poa calls _add_ref() implicitly impl->_remove_ref(); // release the servant since we are finished with it return ptr; } N.B. when you call _this() to implicitly activate the object (or POA::activate_object() to explicitly activate it) the POA increases the reference to ensure that it is kept alive while it is in the active object map. 3) Create a remove() operation on your CORBA interface. In the implementation of this operation, call POA::deactivate_object(). This will ensure that after the operation has completed (and in addition, any concurrent operations have completed), the servant's reference will be decremented, and the servant will be deleted. E.g. void test_impl::TransientObj_impl::remove() { PortableServer::POA_var poa = _default_POA(); PortableServer::ObjectId_var oid = poa->servant_to_id(this); poa->deactivate_object(*oid); } Hope this helps, Cheers, Phil |