WeakRef usage

There was a good question from Markus in a recent comment on a different post of mine.

In children of a window we should keep track of the parent window by using WeakRef.
But what if I have a class cDepartment with a list of employees defined as Employees() as cEmployee – should that then better also be defined as WeakRef? And why or why not?

First I’ll say “it depends” as there’s certainly no single correct answer to such a question. In many cases it will depend on the expected usage.

WeakRefs are a curious thing. In Xojo most times you have a reference to an object its a strong reference. What happens is that the objects reference count is increased and only when that counter gets set to 0 will the object be destroyed.

For instance, if we have code like the following

Class Foo

  Sub Destructor()
    break
  End Sub

End Class


dim firstRef as Foo
dim secondRef as Foo

firstRef = new Foo 
// the object firstRef refers to now has a reference count of 1

secondRef = firstRef 
// since secondRef refers to the SAME object as firstRef
// the object firstRef refers to now has a reference count of 2

firstRef = nil
// the object firstRef refers to now has a reference count of 1

secondRef = nil
// the object firstRef refers to now has a reference count of 0
// and it will be destroyed and the breakpoint in the destructor
// will be encountered

Now what happens if we use a WeakRef instead for secondRef ? If we turn that code into the following

Class Foo

  Sub Destructor()
    break
  End Sub

End Class


Dim firstRef As Foo
dim secondRef as Foo
Dim weakSecondRef As WeakRef // <<<<<<< note the type !

firstRef = New Foo 
// the object firstRef refers to now has a reference count of 1

weakSecondRef = New WeakRef(firstRef)
// since weakSecondRef is a WeakRef the object 
// firstRef refers does NOT increment its reference count

firstRef = Nil
// the object firstRef refers to now has a reference count of 0
// and it will be destroyed and the breakpoint in the destructor
// will be encountered now

// but what about weakSecondRef's contents ???
// lets fetch that value and see whats in there now
secondRef = Foo(weakSecondRef.Value)

break // <<< here you will find that the returned value is NIL !

And if you try to use the object contained by the weakref secondRef you will find that it is nil. A weakref allows an object to be referenced in a way that it does not increment the original objects reference count which CAN let that object be nil’d in other code.

When you use a weakref you MUST check the VALUE of the weakref to see if what you get back is NIL because the object may have been set to nil elsewhere.

Now that we have the basics of weakrefs out of the way lets turn back to Markus’ original and my original reply of “it depends”.

n children of a window we should keep track of the parent window by using WeakRef.

Indeed you may want to have child windows retain a weakref to refer to a parent window. It would allow you to close the parent and not the child, as the weakref will not increment the reference count of the parent window. But, you may want the parent to not be set to nil when there are child windows.

This decision will depend entirely on how your UI is supposed to work. If those child windows should not exist without a parent then a hard reference to the parent may make perfect sense.

But what if I have a class cDepartment with a list of employees defined as Employees() as cEmployee – should that then better also be defined as WeakRef? And why or why not?

Again this will depend entirely on how the cDepartment class should behave. Can cEmployees be added & removed at runtime and should the cDepartment class be able to deal with this ? Or should cDepartment need to be reconstituted when such changes of its employees are made ? The correct behaviour isnt dictated by the underlying code and whether you should use weakrefs but by the needs of the application and how cDepartment should behave.

You could always use weakrefs but this could have unintended consequences for the cDepartment class as this would allows its cEmployees to be removed at runtime. If you had used a FOR EACH loop with an iterator to perform some function you would need to handle the exceptions that could be encountered. Iterators will be invalidated by removal of an employee while iterating over the list and will raise an exception of this occurs. Weakrefs would permit this. Hard references would not.

2 Replies to “WeakRef usage”

    1. Any time – it was actually a good question you originally posed and one that doesnt seem to be covered well anywhere else

Comments are closed.