Hi,
I tried to bring up this subject a view days ago, but without much success.
Very good that it's brought up again. Meanwhile I thought about the problem
myself.
Another way to solve this problem is to look for circular references upon
unset. This might be bad for performance, but I believe that preventing a
memory leak is something that is the responsibility of PHP, not of the user.
----
The unset() statement could do something like the following (pseudo code):
void unset(object) {
object->refcount--;
list = new Linked_List(); // Linked list with counter for each item
count_references(list, object);
foreach (list->items as item) {
if (item->count != item->object->refcount) return;
}
foreach (list->items as item) {
destroy(item->object);
}
}
void count_references(list, object) {
if (list->has_object(object)) {
list->inc_count(object);
return;
}
list->add(object);
foreach (object->children as child) {
count_references(list, child);
}
}
-----
It's important that when an object is destroyed because refcount is 0,
unset() is called for all it's children. Also when a variable is unset
because of leaving the call stack, unset() should be used. When destoy() is
called, it is not necessary to call unset() this.
-----
Imagine the following situation:
$x --> A --------> B --> C <--> D
$y -| | ^ |
->F <-> G | |-> E <-- $z
| |
-------------|
$% is a reference within global or static space or within the call stack.
//--- Example 1 ---
unset($x); // Would simply lower the refcount of A
unset($y); // Would destroy A, F and G, but not the rest
unset($z); // Would destroy the rest (B, C, D and E)
//--- Example 2 ---
unset($z); // Would simply lower the refcount of E
unset($x); // Would simply lower the refcount of A
unset($y); // Would destroy everything
-----
I don't think writing a magic unset method will do the trick, because would
cause a problem if you would do:
$a = new MyClass();
$b = $a;
unset($b);
Also when refcount is lowered because of leaving the call stack, calling
unset would cause a problem. Not calling unset would still cause the memory
leak.
I've I'm correct, the method should work in all situations.
Best regards,
Arnold Daniels
Javeline - Create what's next.
http://www.javeline.net
-----Original Message-----
From: news [mailto:news@sea.gmane.org] On Behalf Of Sebastian Bergmann
Sent: zondag 10 december 2006 17:26
To: internals@lists.php.net
Subject: Re: [PHP-DEV] Re: [RFC] Magic Method that handles unset($object)
Sara Golemon wrote:
> To do this >right< you'd need notification, not just that unset() was
> called on the object, but what the current state of *both* of its
> relevant reference counts are.
I fail to see why. If we introduce a method that is called for
unset() then there should be no problem with resetting the
$children attribute to array() in my example:
unset($parent) -> "magic method" -> $children = array() -> no
references to $child objects
Nothing would happen in the case that you describe where other
references to the $child objects exist, of course.
--
Sebastian Bergmann http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php