Re: Appropriate dealloc and finalize actions
Re: Appropriate dealloc and finalize actions
- Subject: Re: Appropriate dealloc and finalize actions
- From: Roland King <email@hidden>
- Date: Mon, 12 Oct 2009 21:05:06 +0800
No. Under GC you don't have this problem at all. You don't need
weak references or anything else funky, it just works. MyClass1
pointing to MyClass2 and back with ordinary object references/
assign properties does create a cycle yes, however GC can manage
that perfectly well. Once there are no references to either
MyClass1 or MyClass2 from the *ROOT* objects, even though they
point to each other, they are subject to collection. GC is able to
deal with these reference loops quite happily.
Of course you’re right, you do not need weak references under GC to
break reference count cycles - these are a non-issue under GC. I
made the implicit assumption (bad bad!) that these objects should
not keep each other alive. This is what __weak is good for: it marks
a reference which does not keep the target alive and is auto-niled
when the target dies. Depends on what you need.
And there’s no need to conditionalize __weak in any way. It’s simply
ignored under non-GC.
Let me see if I can summarize this with an example so the original
poster can decide exactly what fits his purpose, because there's still
room for misunderstanding.
Assume we start with two objects, O1 and O2, each of which has one
strong reference to it (if we're memory managed that means it has been
retained once and not yet released, if GC, it's strongly reachable).
Then let's say each of the following things happen and I'm going for
the sake of example assume no other external factors alter the object
lifetimes, try to keep it simple.
1. O1 and O2 are set to point to each other (each has its connection
set to the other).
2. The strong reference to O1 is removed, so in memory managed mode
it's released, or in GC mode it becomes otherwise non-root-reachable
3. sometime later the strong reference to O2 is removed in the same
way as 2. above.
Here is what I believe happens in each of the cases
a) Memory Managed mode where 'connection' is a 'retain' property.
At 1., the reference counts of O1 and O2 are increased to 2.
At 2., O1's reference count drops to 1 and it is not released.
At 3., O2's reference count drops to 1 and it is not released.
Yes this is your retain cycle as the original poster had said.
b) Memory Managed mode where 'connection' is an 'assigned' property
which does self.connection.connection = nil upon dealloc
At 1. the reference counts of O1 and O2 are unchanged
At 2. O1's reference count drops to 0 and it's released, in doing so
it nil's O2's connection pointer
At 3. O2's reference count drops to 0 and it's released, its
connection pointer was nil'ed earlier, so there's no dangling reference.
This is what the original poster suggested and should work. Note that
O2 can 'lose' O1 at any point, its lifetime depends on things entirely
external to the ownership of O2, but there's no retain cycle and the
reference nil in the dealloc stops one object from trying to use the
other after that's happened.
c) GC mode, normal references (ie connection is an assigned ordinary
property)
At 1. O1 and O2 now have mutual strong references to each other
At 2. O1 loses one strong reference however because O2 is still
strongly reachable, and O1 is strongly reachable from O2, O1 is *not*
subject to reclaimation here. They both continue to hang around.
At 3. O2 loses its strong reference. O1 and O2 *still* strongly
reference each other however, because they no longer have a path from
a root object, they are now subject to being reclaimed.
This is what I assumed (and true I have also made an assumption) is
the most likely useful case. Unlike in b) where each object could lose
its connected object at any point, in c) as long as *one* of the
objects is strongly reachable, its reference to its partner keeps its
partner object alive, however when *neither* of them are strongly
reachable from root objects, the fact they refer to each other only,
is not enough to keep them alive. This is where GC wins.
d) GC mode, _weak references between O1 and O2
At 1. O1 and O2 have weak references to each other
At 2. O1 is now not strongly reachable from the root and, because the
reference to O1 from O2 is weak, that does not make a strong reference
path and O1 *may* now be collected at any point. Doesn't have to be,
the GC can take it anytime it likes.
At 2. O2 is also now not strongly reachable and it is also subject to
reclaimation. At some point after this O1 and O2 will be collected.
d) is the closest GC analogue to b), it's very much like it. The
objects don't affect each other's lifetimes at all, and when one
object is collected the reference from the other object is nil'ed as
it was in b). The only difference really is that in b) (the way I set
this example up), O1 *will* be dealloc'ed at stage 2., the point it's
released, in d) it may or may not be dealloced there, or sometime
later or never.
I would personally expect that in most cases c) is what you want if
you can have it, and it's something garbage collection really helps
with. If you really really wanted b), to have these connections not
affect the objects on the other end at all, then _weak references will
do that in a GC model.
I'm sure I have some errors and poor terminology there and stand ready
for correction (or collection).
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden