LifeCycle services: remove()

Duncan Grisby dpg1001@cam.ac.uk
Tue, 3 Feb 1998 13:29:35 +0000 (GMT)


On Mon, 2 Feb 1998, Fred Eisele wrote:

> I believe that the <CosLifeCycle::LifeCycleObject> is inherited by
> the appropriate interface, call it <interface X>, as follows:
> 
>          interface X : ::CosLifeCycle::LifeCycleObject { string y; };
> 
> Now there is on obligation on the implementation side
> for the X_Impl object to "know" how to <remove()> itself.

This has to be the case, because only the implementation can know what
it has been up to, and what it may need to clean up.

> How is this intended to be done?
> Does the implementation call its own destructor? ( delete this; )
> Is there a safe way to do this?

The correct way to do it is to call the _remove() function, then call
BOA::dispose(this). The _remove() causes the location tracking at the home
location to be cleared up. The dispose() un-registers the CORBA object
from the ORB, and also calls the C++ object's destructor once the
reference count becomes zero. 

The code from the echolag example is:

  void
  EchoLag_i::remove() {
    omniLC::ThreadLC zz(this);
    _remove();
    CORBA::BOA::getBOA()->dispose(this);
  }

> In your example you have the following:
> 
> void
> _lc_sk_EchoLag::_remove()
>  {
>     if (_home_EchoLag->is_proxy())
>       omniLC::_wrap_proxy::_reset_wraps(this);
>     _get_linfo()->reportRemove();
>  }

This is part of the generated code, so you shouldn't have to worry about
it. For completeness, I'll explain what it's up to.

The call to reportRemove() informs the home location that the object has
been removed, causing it to clear up the home location wrapper.

To understand the first bit, I need to explain more about what happens
when objects are moved:

Suppose I create an object at location A, and a client to it at location
B.  B holds a proxy object which performs marshalling for the object's
operations. Now suppose I move the object implementation from A to B. What
we want is for calls which used to go via the proxy to go straight to the
new implementation object. 

This is achieved by having a wrapper to the proxy, of class _wrap_proxy_*. 
The client holds a pointer to the wrapper object, which forwards all
operation invocations to either a normal proxy object, or an actual
implementation. When the implementation moves again, or is removed, these
_wrap_proxy_* objects must be reset to point to the original home location
object. This is done by calling the static function _reset_wraps() within
the _wrap_proxy base class, but only if the implementation is in a
different address space to the home location. 

The _reset_wraps() function resolves to calls to _reset_proxy() on each
_wrap_proxy_* object.


> Or, is the intent to call the object's <delete()> function directly?

You should definitely not do this, as the ORB won't realise that the
object has been deleted.

> Or, is it the BOA's job to call the delete:
> 
>   CORBA::BOA::getBOA()->dispose(this);

This is the way to do it.

> Is it appropriate for an object to delete itself if it returns void?
> Are you playing some game where the object returns first and
> then has itself deleted (by the BOA)?

As I said (much) earlier, the call to dispose() un-registers the object,
then deletes it as soon as its reference count becomes zero. While an
operation invocation occurs, the ORB increments the object's reference
count. So, the object is not deleted until the operation invocation is
over. This means that you could return a value from an operation which
removed the implementation object. 

> If this is in covered in one of the documents, sorry I missed it.

The general gist of it is covered by a combination of the CORBA spec, the
omniORB2 user guide, and the omniLifeCycle guide. Some of it is only
covered if you count source code as documentation :-).

> Do you know of where to obtain documentation on a "correct/complete"
> implementation of the LifeCycle service?

In my opinion, the CosLifeCycle service is over-complicated for many
occasions when you wish to do LifeCycle-like operations, so I thought it
was best to provide the functionality required to implement it, rather
than a full implementation of it. There is also the technical point that
it requires the use of the any type, which the current public release does
not support.

Some ORBs, such as the now-defunct HP ORBPlus, provide implementations of
the FactoryFinder and GenericFactory interfaces, but fail to support the
fundamental move operation.


Let me know how you get on. I did the LifeCycle support because I need it
myself; it will be interesting to hear other peoples' experiences with it. 


I hope this helps,

Duncan.

-- 
 -- Duncan Grisby                                         --
  -- dpg1001@cam.ac.uk                                     --
   -- finger dpg1001@badges.cl.cam.ac.uk for PGP public key --