avalon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Leif Mortenson <leifli...@tanukisoftware.com>
Subject Re: [Fortress] Cyclic loops
Date Mon, 30 Jun 2003 09:29:47 GMT


Anton Tagunov wrote:

>3)
>The issue may be partially resolved by allowed a component to
>declare a dependency on its own role. (Probably this has already
>been done and that's how excalibur-store compiles fortress
>meta-data, but then why are you having troubles?)
>
>In fact it is quite reasonable to allow a component to look up
>its own role and not consider it a cyclic dependency. If I want
>to get myself via a lookup() why not allow me to do this?
>
Hmmm.  I think that a loop is a loop.  Roles may be fine.  But a component
instance should not be able to lookup itself as the returned instance would
not yet have been initialized.

>4.2)
>(I hope my poor knowledge of terminology has not stopped me from
>being understandable here :)
>
Not at all.  Your English is much better than my Russian. :-)  I can 
relate when
using my Japanese though :-)

>7)
>
>This section is a sort of "RT" :-)
>
>Are the loops evil after all?
>
>Can there be a legitimate application where two components need
>to lookup() each other?
>
>Why not?
>
>The real trouble will happen if the components
>invoke each other during the "warmup" peirod.
>
>("warmup" = contextualize, configure, service, initialize, start)
>
>But if the components do not make any real calls on each other
>until after "warmup", then its all ok!
>
Actually, I don't think it should be up to the component to worry about 
when it can
actually make use of components that have been obtained via a lookup. 
 So I think
it is good that the Container makes sure that components do no declare any
loops.

The question is how to handle lookups whose lifecycles are managed by the
component.  This is how I have handled systems that must contain actual 
loops.
For example. If you have 4 components CA, CB, CC, and CD.  You can declare
that CB depends on CA, CC depends on CB, and CD depends on CA.  Fortress
will correctly load CA then CB, then CC, and finally CD.  The problem is 
that
CA also needs to call methods in CD.  The declaration that CA depends on CD
will not work because this would create a loop that would prevent the 
container
from being able to guarantee that all components are initialized before 
being
looked up.

I have worked around this by wrapping the call to lookup CD in CA in a 
lookup
release block.  This means that the lookup and release must be done for each
call,  But if I make sure that CD can not be disposed while a call is 
being made

CD cd = (CD)sm.lookup( CD.ROLE );
try
{
    cd.doSomething();
}
finally
{
    sm.release( cd );
    cd = null;
}

Even this method is not perfect on its own if doSomething takes a while to
execute.  Fortress does not wait until all looked up references have been
released before disposing a component.  It simple guarantees that the
components will be disposed in the correct order.  Meaning
CD->CC->CB->CA in this case.

The problem is that the above will dispose CD while its doSomething method
is being called by CA.  This can lead to NPE's if CD's dispose method is
called before doSomething has completed.

This is a hack, but I have worked around this by implementing a call 
counter in
all methods of CD that are exposed.
public void doSomething()
{
    synchronized(this)
    {
        m_calls++;
    }
    try
    {
        // Actually do something
    }
    finally
    {
        synchronized(this)
        {
            m_calls--;
            this.notifyall();
        }
    }
}

Then in the components dispose method, wait until the m_calls counter
has dropped to 0.   This will work most of the time, but there is still a
slight chance that the thread from CA will lookup the CD component just
before it is disposed and the dispose method will be called before the
doSomething() is actually called.   This is only an issue at application
shutdown, so it was an acceptable workaround at the time.

It would be nice if the container handled this kind of thing correctly.

It should be possible to create a lookup counter that tracks the number
of times that a component.  The counter would then be checked before a
component was disposed and the counter would wait up to a timeout limit
before disposing the component.  The container would prevent any new
references to the component from being looked up once the shutdown
process was initiated.

Thoughts?

Cheers,
Leif


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Mime
View raw message