What is a "weak" reference

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
26 messages Options
12
Reply | Threaded
Open this post in threaded view
|

What is a "weak" reference

Rob Rothwell
Can someone explain what a "weak" vs (I am guessing) "strong" reference is?  I have been struggling with Garbage Collection for quite some time now and saw this on another list:

"You'll need to add an instance variable to process and modify fork to record the origin.  Currently processes don't remember their ancestor.  I recommend you create a special fork that remembers ancestry, rather than modifying the default fork.  You will potentially accumulate a lot of garbage otherwise.  Also, you might consider making the reference from a process to its parent weak to allow the parent to be GC'ed when it terminates even if it has children."

I, too, am maintaining parent/child relationships in my application and have just been doing something like:

Parent>>createChild
     |child|
     child := Child new parent: self.
     ^child

I am assuming, given my troubles, that this is NOT a weak reference?!

Thank you,

Rob


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Michael Davies-2
On Sun, Jul 13, 2008 at 6:15 PM, Rob Rothwell <[hidden email]> wrote:
> Can someone explain what a "weak" vs (I am guessing) "strong" reference is?
[snip]
> I, too, am maintaining parent/child relationships in my application and have
> just been doing something like:
> Parent>>createChild
>      |child|
>      child := Child new parent: self.
>      ^child
> I am assuming, given my troubles, that this is NOT a weak reference?!

Hi Rob,
Have a look at the class comment on WeakArray: "WeakArray is an array
which holds only weakly on its elements. This means whenever an object
is only referenced by instances of WeakArray it will be garbage
collected."

My understanding of this is that garbage collection is done by
reference counting, and so the situation you described may result in
parent and child forming a circular reference to each other, and so
never being collected - but it depends on what you do with that return
value.

I note that there are very few uses of any Weak* classes in the image,
so it's likely that there is a better way of implementing what you're
aiming for; eg the child could drop its direct parent reference, and
do something like

Child>>parent
    ^ Parent allInstances detect: [ :each | each children includes: self ]

(or vice versa depending on which way you're more likely to traverse
the relationship).

This is just me thinking out loud though - perhaps someone else could
comment on best practice in this case. "Smalltalk Best Practice
Patterns" is very useful in answering these types of questions, but my
copy is in a box somewhere at the moment.

Hope this helps, Michael
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Randal L. Schwartz
>>>>> "Michael" == Michael Davies <[hidden email]> writes:

Michael> I note that there are very few uses of any Weak* classes in the image,
Michael> so it's likely that there is a better way of implementing what you're
Michael> aiming for; eg the child could drop its direct parent reference, and
Michael> do something like

Child> parent
Michael>     ^ Parent allInstances detect: [ :each | each children includes: self ]

Michael> (or vice versa depending on which way you're more likely to traverse
Michael> the relationship).

I'd argue though that a solution that involves #allInstances has a bit of code
smell.  For example, consider an XML node, looking for its parent.  In a given
parsed document, you'll likely have thousands of nodes, and it would be
clearly inefficient to continually find the one parent by asking all of them.
In that case though, weak refs probably weren't needed anyway, since each node
can just contain its parent.

Michael> This is just me thinking out loud though - perhaps someone else could
Michael> comment on best practice in this case. "Smalltalk Best Practice
Michael> Patterns" is very useful in answering these types of questions, but my
Michael> copy is in a box somewhere at the moment.

Absolutely.  A clearly seminal book.  My dog-eared copy is within reach, at
least when I'm in my home office.  Too bad Kent has gone off to the Java, and
now C# realm, if I heard right.

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[hidden email]> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Herbert König
In reply to this post by Michael Davies-2
Hello Michael,


Child>>>parent
MD>     ^ Parent allInstances detect: [ :each | each children includes: self ]

allInstances scans *every* object in the image which is slow.

The garbage collector needs a path to a root object (whatever that is)
so a purely circular reference does not prevent garbage collection of
parent and child.

--
Cheers,

Herbert  

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

tblanchard
In reply to this post by Rob Rothwell
A weak reference is simply a reference that will not prevent an object  
from being garbage collected.  It is common to use a weak reference in  
back pointers when you know you are having circularities.  It is  
practically a pattern, when building a hierarchy of objects, to make  
the parent pointer in parent child type structures a weak reference.

So how do you make a weak reference? You stick a WeakArray in as a  
holder.  So in your parent/child objects you would write something like:

Node>>parent
        ^ parent ifNotNil: [parent first] ifNil: [parent]

Node>>parent: p
        parent := p ifNotNil: [WeakArray with: p] ifNil: [p]

thus using a WeakArray as a holder for the parent.

When a weak reference gets garbage collected, its weak references are  
set to nil first.



On Jul 13, 2008, at 9:15 AM, Rob Rothwell wrote:

> Can someone explain what a "weak" vs (I am guessing) "strong"  
> reference is?  I have been struggling with Garbage Collection for  
> quite some time now and saw this on another list:
>
> "You'll need to add an instance variable to process and modify fork  
> to record the origin.  Currently processes don't remember their  
> ancestor.  I recommend you create a special fork that remembers  
> ancestry, rather than modifying the default fork.  You will  
> potentially accumulate a lot of garbage otherwise.  Also, you might  
> consider making the reference from a process to its parent weak to  
> allow the parent to be GC'ed when it terminates even if it has  
> children."
>
> I, too, am maintaining parent/child relationships in my application  
> and have just been doing something like:
>
> Parent>>createChild
>      |child|
>      child := Child new parent: self.
>      ^child
>
> I am assuming, given my troubles, that this is NOT a weak reference?!
>
> Thank you,
>
> Rob
>
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://lists.squeakfoundation.org/mailman/listinfo/beginners

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Rob Rothwell
On Mon, Jul 14, 2008 at 11:42 AM, Todd Blanchard <[hidden email]> wrote:
So how do you make a weak reference? You stick a WeakArray in as a holder.  So in your parent/child objects you would write something like:

Node>>parent
       ^ parent ifNotNil: [parent first] ifNil: [parent]

Node>>parent: p
       parent := p ifNotNil: [WeakArray with: p] ifNil: [p]

thus using a WeakArray as a holder for the parent.

When a weak reference gets garbage collected, its weak references are set to nil first.

Thank you!  This is what I wanted to know; I'll give this a try, and see how it works for me...

So many Classes, so little time...

Rob


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Michael Davies-2
In reply to this post by Herbert König
On Mon, Jul 14, 2008 at 4:43 PM, Herbert König <[hidden email]> wrote:
> Hello Michael,
>
>
> Child>>>parent
> MD>     ^ Parent allInstances detect: [ :each | each children includes: self ]
>
> allInstances scans *every* object in the image which is slow.

Ouch, I can see that it would be :-)

> The garbage collector needs a path to a root object (whatever that is)
> so a purely circular reference does not prevent garbage collection of
> parent and child.

Thanks, that's interesting - does that mean that the parent-child
linkage in Rob's example isn't the root cause of his problem?
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Bert Freudenberg
In reply to this post by Rob Rothwell

Am 14.07.2008 um 09:51 schrieb Rob Rothwell:

> On Mon, Jul 14, 2008 at 11:42 AM, Todd Blanchard  
> <[hidden email]> wrote:
> So how do you make a weak reference? You stick a WeakArray in as a  
> holder.  So in your parent/child objects you would write something  
> like:
>
> Node>>parent
>        ^ parent ifNotNil: [parent first] ifNil: [parent]
>
> Node>>parent: p
>        parent := p ifNotNil: [WeakArray with: p] ifNil: [p]
>
> thus using a WeakArray as a holder for the parent.
>
> When a weak reference gets garbage collected, its weak references  
> are set to nil first.
>
> Thank you!  This is what I wanted to know; I'll give this a try, and  
> see how it works for me...
>
> So many Classes, so little time...

Well, Todd certainly knows when he needs to introduce weak refs but a  
simple parent-child relation (say, in a tree) is *not* a good example  
for this. The parent reference in a child does not prevent it from  
being garbage-collected, unless there exist other references to it.  
You cut the child link and it's gone. But if there are indeed other  
references to the child weak refs would just mask the problem because  
the parent may get garbage-collected but the child is not. The problem  
in that case typically is not the parent/child links but those other  
references.

In a clean design you very rarely need weak refs. Also, you need to  
sprinkle your code with ifNil: tests because a weak ref can become nil  
any time.

- Bert  -


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Herbert König
In reply to this post by Michael Davies-2
Hello Michael,


MD> Thanks, that's interesting - does that mean that the parent-child
MD> linkage in Rob's example isn't the root cause of his problem?

see Bert's reply, he knows why it is so, I only know that I do it all
the time (circular links) and it never prevents GC.



--
Cheers,

Herbert  

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Michael van der Gulik-2
In reply to this post by Michael Davies-2
On Mon, 14 Jul 2008 12:07:51 +0200
"Michael Davies" <[hidden email]> wrote:

> On Sun, Jul 13, 2008 at 6:15 PM, Rob Rothwell <[hidden email]> wrote:
> > Can someone explain what a "weak" vs (I am guessing) "strong" reference is?
> [snip]
> > I, too, am maintaining parent/child relationships in my application and have
> > just been doing something like:
> > Parent>>createChild
> >      |child|
> >      child := Child new parent: self.
> >      ^child
> > I am assuming, given my troubles, that this is NOT a weak reference?!
>
> Hi Rob,
> Have a look at the class comment on WeakArray: "WeakArray is an array
> which holds only weakly on its elements. This means whenever an object
> is only referenced by instances of WeakArray it will be garbage
> collected."
>
> My understanding of this is that garbage collection is done by
> reference counting, and so the situation you described may result in
> parent and child forming a circular reference to each other, and so
> never being collected - but it depends on what you do with that return
> value.

Squeak's garbage collector is a generational mark/sweep garbage collector. It does not use reference counting.

http://wiki.squeak.org/squeak/1469 (unfortunately the page has a dead URL in it).

Gulik.


--
Michael van der Gulik <[hidden email]>
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

David T. Lewis
In reply to this post by Bert Freudenberg
On Mon, Jul 14, 2008 at 10:43:30PM -0700, Bert Freudenberg wrote:
>
> In a clean design you very rarely need weak refs. Also, you need to  
> sprinkle your code with ifNil: tests because a weak ref can become nil  
> any time.

It is also worth mentioning that weak references can lead to performance
problems, particularly if you use a lot of them. The process of cleaning
up weak references happens in the background, and is not very efficient
if a lot of weak references need to be scanned. The end result is that
your Squeak image will gradually become very slow, for no obvious reason.
Bert's observation on design is the best reason to avoid using weak
references, but if you need more convincing, consider performance ;)

Dave
 
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

cedreek
All that sounds like "don't use weak reference" :)


Cédrick

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Herbert König
Hello cdrick,


c> All that sounds like "don't use weak reference" :)

.... unless you know exactly what you are doing.


--
Cheers,

Herbert  

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Michael Davies-2
In reply to this post by cedreek
On Tue, Jul 15, 2008 at 2:39 PM, cdrick <[hidden email]> wrote:
> All that sounds like "don't use weak reference" :)
>
>
> Cédrick
>

A nice clear summary!

Thanks to all who have posted on this topic - it's been a very useful
discussion.

Michael
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Marcin Tustin
In reply to this post by cedreek
One of the uses of weak references in other languages is to keep a collection of all the instances of a class without preventing them being garbage collected. Obviously, this is not necessary in squeak.

On 7/15/08, Herbert König <[hidden email]> wrote:
Hello cdrick,


c> All that sounds like "don't use weak reference" :)

.... unless you know exactly what you are doing.


--
Cheers,


Herbert


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Bert Freudenberg
Am 15.07.2008 um 06:42 schrieb Marcin Tustin:

> One of the uses of weak references in other languages is to keep a  
> collection of all the instances of a class without preventing them  
> being garbage collected. Obviously, this is not necessary in squeak.


One major use in Squeak is for ensuring that system resources (such as  
file handles) are released when a file object is garbage-collected.  
Note this is only a fall-back, you should still use #close on files,  
but to prevent resource leakage in odd cases, a weak reference is held  
to each open file.

It's one of the low-level implementation details that exist to make  
the normal live of a Smalltalk programmer simpler. Only the framework  
designer interfacing to non-Smalltalk objects (such as files) needs to  
worry about it. I've never seen a need for weak references in  
application-level code.

- Bert -


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Randal L. Schwartz
In reply to this post by Herbert König
>>>>> "Herbert" == Herbert König <[hidden email]> writes:

Herbert> Hello cdrick,
c> All that sounds like "don't use weak reference" :)

Herbert> .... unless you know exactly what you are doing.

One possible use I haven't seen in this thread is to "keep notes" on a class
you don't own (and don't want to change), without preventing them from being
GC'ed normally.

For example, if I wanted to write a system watcher that noticed the comings
and goings of Process objects, I'd likely keep a Dictionary keyed by the
Process instance referencing the data of start times.  However, I wouldn't
want that key to keep the Process instance from being gc'ed, so I'd use a weak
dictionary.  This is how the classic "dependents" system works as well: the
dependencies are in a WeakDictionary so that when the watched object goes
away, the dependencies are also cleaned.

The alternative is to add a set of properties to the Process that others can
stuff information, so that "Process allInstances" can get my process watcher
what it needs instead.

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[hidden email]> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Herbert König
Hello Randal,

RLS> dictionary.  This is how the classic "dependents" system works as well: the
RLS> dependencies are in a WeakDictionary so that when the watched object goes
RLS> away, the dependencies are also cleaned.

thanks for some free education (no smiley, I mean it), now I'll do
some homework and look up dependency.

I use it in some places without knowing of it's "weakness".


--
Cheers,

Herbert  

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Bert Freudenberg

Am 15.07.2008 um 08:26 schrieb Herbert König:

> Hello Randal,
>
> RLS> dictionary.  This is how the classic "dependents" system works  
> as well: the
> RLS> dependencies are in a WeakDictionary so that when the watched  
> object goes
> RLS> away, the dependencies are also cleaned.
>
> thanks for some free education (no smiley, I mean it), now I'll do
> some homework and look up dependency.
>
> I use it in some places without knowing of it's "weakness".


The dependents are weak only for "regular" objects. Proper Models  
handle their own dependents collection in a non-weak manner.

- Bert -


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: What is a "weak" reference

Nicolas Cellier-3
Bert Freudenberg a écrit :

>
> Am 15.07.2008 um 08:26 schrieb Herbert König:
>
>> Hello Randal,
>>
>> RLS> dictionary.  This is how the classic "dependents" system works as
>> well: the
>> RLS> dependencies are in a WeakDictionary so that when the watched
>> object goes
>> RLS> away, the dependencies are also cleaned.
>>
>> thanks for some free education (no smiley, I mean it), now I'll do
>> some homework and look up dependency.
>>
>> I use it in some places without knowing of it's "weakness".
>
>
> The dependents are weak only for "regular" objects. Proper Models handle
> their own dependents collection in a non-weak manner.
>
> - Bert -

Hmm, not really

"Warning: this example is stupid!"
| tmp |
tmp := Model new.
tmp addDependent: #x.
tmp addDependent: #y.
tmp dependents class. "=> DependentsArray"

DependentsArray is a class that holds weakly to its elements...

The difference is that the DependentsArray itself don't have to pollute
the global WeakIdentityKeyDictionary (Object classPool at:
#DependentsFields).

But maybe we have just quit the beginners rails...

Nicolas


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
12