[gclist] Dgc algorithm for catching cycles

Arturo Bejar arturo@communities.com
Sun, 9 Jun 96 22:14:21 +0100


Hi all,

Rick Hudson sent me the following concerns about the algorithm I posted 
earlier this weekend, the answer addresses issue (iv) raised by Gustavo 
Rodriguez-Rivera:

>	iv.  Back-references may change during back-tracing

Rick Hudson wrote: 

>Consider....
>
>We have 4 objects A B C and M. M is a rooted object that holds pointers for
>the Mutator. The A -> B-> C -| cyclic structure with a pointer from M
>                 ^-----------|
>
>to C. For this example assume no other pointers are relevant and A is 
>'suspect.'
>We used the rules you numbered below. 
>
>Rule 0.0 - B gets a AreYouRooted(n) message from A at time 1.  
>M creates a pointer to A at time 2  
>M destroys the pointer to C at time 3.  
>Rule 1.2 - B sends a AreYourRooted(n) message to C at time 4. 
>Rule 1.2 - C sends a AreYouRooted(n) to A at time 5. 
>Rule 1.3 - A sends a disregard(n) to C at time 6 (ignoring the pointer from
>           M).
>Rule 2.2 - C sends a disregard(n) to B at time 7. 
>Rule 2.2 - B sends a disregard(n) to A at time 8. 
>Rule 3.2 - A self destructs at time 9. M is left holding a 
>           pointer with a worthless A.
>
>There are other devious things M can do but this one is the simplest I could
>think of.
>
>Let me know what I missed.
>
>- Rick Hudson
>hudson@cs.umass.edu

Rick,

Thanks for your feedback. As you probably know a distributed system there 
is not much one can do about constantly changing references, there is no 
inexpensive way to establish a lock like you can with a local gc.

In a way, because of network latency, the algorithm is run for a very 
relative time t on the network, so on the way out the reference graph 
will be at time t for the first node, (t + latency), for any node node (t 
+ latency1 + ...), and then you add them on the way back, this would 
apply to any algorithm.

There are a number of ways to address your point, the formal way is that 
[A], as any other node can detect a change in the set of objects directly 
referring to it, and you have to choose a policy to address them, i.e. if 
while A is waiting for a response from B it notices that a new reference 
to it (from [M]) has showed up, so it sends a message with the same (n) 
to [M], which will be replied postively. If [M] is the same machine 
boundary as [A], [A] will just become locally rooted again.

We can tell these changes easily because we are using the mark & sweep of 
the local Java GC to build the inverse reference graph of a specific set 
of objects, which we then work on.

The second way of handling it is implementation related, we don't 
actually destroy A but we make it drop the remote references that it 
holds and the remote references to it (the pointer to B in this case), 
something that could happen in a network failure or partition, as is 
usual with distributed programming any object that has to talk to another 
across a machine boundary needs to be able to cope with failiure. Then we 
let the local GC clean it up.

We could follow a more agressive strategy for cleaning up the cycle by 
sending terminate messages, but those could be spoofed, if all of the 
machines that were running the algorithm were in a trusted boundary, like 
a company, then we can pursue much more agressive collection strategies.

Let me know what you think,
Arturo

___________________________________________________________________
Arturo Bejar                   "What you can see, you can achieve."
arturo@communities.com                          - J. Verne, sort of