Since Weak references is already an established concept in many OOP
languages a lot can be learned from their implementation. A lot of the
potential related problems and solutions has already been studied.
Anyone who wish to contribute to this feature should start by reading
this excellent article by Ethan Nicholas:

http://weblogs.java.net/blog/2006/05/04/understanding-weak-references

For example I previously stated that I wanted a callback to clean up
the weak reference object and indexes in the collection - then came to
the conclusion that __destruct method would suffice for this. Then I
read this part:

<quote>
Reference queue
Once a WeakReference starts returning null, the object it pointed to
has become garbage and the WeakReference object is pretty much
useless. This generally means that some sort of cleanup is required;
WeakHashMap, for example, has to remove such defunct entries to avoid
holding onto an ever-increasing number of dead WeakReferences.

The ReferenceQueue class makes it easy to keep track of dead
references. If you pass a ReferenceQueue into a weak reference's
constructor, the reference object will be automatically inserted into
the reference queue when the object to which it pointed becomes
garbage. You can then, at some regular interval, process the
ReferenceQueue and perform whatever cleanup is needed for dead
references.
</quote>

Java utilizes a "ReferenceQueue" that tracks dead references so you
can process and clean up dead references which is an excellent design
solution. The Queue part is not that important, the references might
as well be organized in a LIFO than a FIFO but a FIFO conceptually
more fitting. Imaging dead references standing in a queue, awaiting
cleanup.

The solution is also superior to the __destruct solution since you
would have to extend or modify the class and override the __destruct
method. It makes it impossible to separate the "how the instances is
externally stored"-design from the actual class itself, ergo: you
can't cache classes in external libraries without hacking the
libraries.

I therefore propose changing the constructor (and implementation) to:

void   SplWeakRef::__construct(object ref, SplQueue ref_queue = null)

If the SplWeakRef is given a ref_queue, it will call
ref_queue->push($this) whenever it becomes invalid. If additional
cleanup is required (if you want to catch the event and do cleanup
immediately) one could simply extend SplQueue and overload
SplQueue::push().

Note that resurrection must be avoided so the SplWeakRef does not flip
between valid -> invalid and then turns valid again (this would be a
confusing behavior which can lead to unintentional behavior = bugs).
The implementation should therefore make sure the SplWeakRef does not
turn invalid before __destruct has been run for the object since
__destruct can resurrect an object.

~Hannes

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to