[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: deferred deallocation of local objects
Re: deferred deallocation of local objects
Sat, 18 Oct 2003 10:05:04 +0100
On Friday, October 17, 2003, at 06:00 PM, Alexander Malmberg wrote:
Anyway, there are several potential solutions, with varying degrees of
beauty and backwards compatibility (I haven't had time to check this
Some obvious solutions involve B, eg. to have B block and wait for a
confirmation from C that it has connected to A and created the proxy
(and this may be how most calls already behave in practice).
However, I don't like the idea of mixing B into this. B should, IMHO,
able to send off the messages and forget about it. Having B block on
each such call would not be good for B's performance. Deferring the
release in B doesn't work because there might be code in B that just
calls exit(0) when it thinks that it's done (and doesn't know that it
needs to wait for C). Also, if B crashes, or the connection between A
and B or B and C dies before the confirmation, O might be released
anyway and C is out of luck.
I agree ... all the ideas I could come up with for B to have a special
role seemed to introduce more complexity and unreliability.
I think a better solution would be to have B send a (oneway)
potentialRetain (or something) to A before sending the information to
C would then send a grabPotentialRetain instead of a normal retain when
creating the proxy.
In A, these retains would maintain a "potential retain count" which
increases by one for each potentialRetain and decreases when
grabPotentialRetain turns it into a normal retain. Ungrabbed potential
retains will keep an object alive, but would timeout after some set
This way, B isn't involved at all after sending its messages (so it can
exit/crash/pull the plug without affecting A and C), we correctly
long delays (until the timeout runs out), and the delays in object
deallocation or no longer than they have to be (as soon as C connects,
the potential retain goes away and the object can be released
I think it would work for this problem, but simply deferring release of
all existing local objects belonging to a connection when that
connection is destroyed might be simpler and work just as well in
(and would not change the DO protocol at all, so it would be backward
That being said ...
I think I've been unintentionally misleading people ... basically
my memory is not great, the original hack was a long time ago, and I'm
only gradually remembering things triggered by going over the code in
detail, looking at old ChangeLog comments, and reading comments from
people on this list etc.
The more I look at it, the more I get back into the mindset and remember
why I did what I did ... the best fix I could come up with (after you
the errors in it) in the limited time I had.
I've been looking at how the retain/release mechanisms should work,
and I'm sure I tried to base it around the simple principle that a
is automatically retained, and is not released until a release message
received from the remote process, or the connection is invalidated.
I think that what should happen is -
When an object is vended byref from A to B, we produce a local proxy
in A (which retains the original object), and a remote proxy in B.
The local proxy in A is retained by the connection and is automatically
destroyed (releasing the original object) if the connection is destroyed
(this event should be deferred so the original object is not released
until some time after the connection is destroyed).
The new remote proxy in B is autoreleased immediately on creation
so that as soon as the message if was associated with completes,
the proxy get destroyed (unless it was retained by some other code
Upon deallocation of the remote proxy, process B sends a release
message to process A, telling it to release its local proxy, and hence
release the original object.
So, vending an object over DO implicitly retains it, and it is not
released until explicitly requested by the remote process (or by loss
Then, if B vend its proxy to C, the proxy in B gets retained, so B will
not send a release to A until C has sent the release to B.
Looks at first sight like a pretty good, simple design but -
So, for our three-way connection problem, I think the only way it can
be happening is if B is closing the connection to A before C establishes
its own connection to A.
However, there is another error condition possible between A and B
without involving C:
A vends O to B (oneway void) producing proxy P in B
B uses P and releases it, sending release message to A
A vends O to B again .... before receiving the release message.
A receives the release message and destroys local proxy releasing O
B receives reference to O from A and tries to use it ...
Your solution would fix the original three-way problem, but not this
two way problem.
I think, for the two way problem, A and B need to keep track of packets
sent between them, and A must ignore a release if it has vended the
object to B again.
I think this means that when B sends a release packet, it needs to be
tagged with the sequence number of the latest message B has received
from A, and when A vends an object, the local proxy must be tagged
with the sequence number of the packet being sent.
This requires change to the DO code which may difficult to do without
breaking backward compatibility ... which is why I introduced version
code in GSTcpPort.m back in March. However, it may be that this
change to dealing with sequence numbers won't break old code ...
I haven't checked thoroughly.
I feel it really needs a free day or two to go through the code in
work out exactly what can be done, and if we can do it without breaking
compatibility, etc. But I have no hope of getting that time in the near
future ... so a detailed discussion on this list and a few more heads
looking at the problem might have to do.
Re: deferred deallocation of local objects, Derek Zhou, 2003/10/16
Re: deferred deallocation of local objects, Derek Zhou, 2003/10/18
- Re: deferred deallocation of local objects, (continued)