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
|