New destructors implementation

php.internals

Andi Gutmans

22 years ago
We've changed the way that objects are destroyed during shutdown to a 2-phase mechanism. First, destructors are called for all of the objects in the store (in no particular order). Afterwards - the object storage and the various symbol tables are destroyed&freed. This has several implications: 1. The dependency problems during shutdown which could cause destructors not to be called under certain circumstances - are gone now. Destructors are always called for all objects, and you can depend on that. 2. A *VERY* important implication is that you cannot, and must not rely in any way on the order of destruction during shutdown. It runs in no particular order. That means that by the time the destructor for your object $foo is called, a reference to some other object $bar may already be post-destruction. Note that it will still be 'intact' and accessible in the sense that if you access it - there won't be crashes. However, if this object does indeed have a destructor, it can be considered semantically wrong to touch this object at this point. 3. The APIs have changed to allow for this new mechanism. Instead of the previous dtor callback, which was supposed to both call the destructor and free the object's storage, there are now two separate callbacks - dtor (call the destructor) and free_storage (guess). Generally, for classes which implement PHP-style objects, you should implement both of these callbacks (though you can probably use the standard dtor callback). For overloaded classes such as SimpleXML, COM, etc. - you will most likely only have to implement the free_storage callback, as there's no destructor per-se. We already went over all the overloaded classes in the php-src CVS and moved most of the dtor callbacks to free_storage. Note that the interface is slightly different between these two callbacks - free_storage doesn't receive the object handle. 4. Last but not least - bug #25541 is now fixed! :) Andi

Andrei Zmievski

22 years ago
On Wed, 04 Feb 2004, Andi Gutmans wrote:
> 3. The APIs have changed to allow for this new mechanism. Instead of the > previous dtor callback, which was supposed to both call the destructor and > free the object's storage, there are now two separate callbacks - dtor > (call the destructor) and free_storage (guess). Generally, for classes > which implement PHP-style objects, you should implement both of these > callbacks (though you can probably use the standard dtor callback). For > overloaded classes such as SimpleXML, COM, etc. - you will most likely only > have to implement the free_storage callback, as there's no destructor > per-se. We already went over all the overloaded classes in the php-src CVS > and moved most of the dtor callbacks to free_storage. Note that the > interface is slightly different between these two callbacks - free_storage > doesn't receive the object handle.
Is there an automatic call to __destruct() method then? Because I'd like my PHP-GTK objects to have that method called upon destruction and I don't feel like reimplementing the mechanism for doing that. - Andrei

Michael Walter

22 years ago
Hi Andi, Andi Gutmans wrote:
> [...] > > This has several implications: > > [...]
> > 2. A *VERY* important implication is that you cannot, and must not
rely in any way on the order of destruction during shutdown. It runs in no particular order. That means that by the time the destructor for your object $foo is called, a reference to some other object $bar may already be post-destruction. Note that it will still be 'intact' and accessible in the sense that if you access it - there won't be crashes. However, if this object does indeed have a destructor, it can be considered semantically wrong to touch this object at this point. Doesn't that render more sophisticated cases of objects with constructors sort of unusable? I mean, any scheme like class Wrapper: ctor: $this->m_resource=alloc_resource(); dtor: $this->m_resource=free_resource(); doWork(): do_this_and_that($this->m_resource); class Client: ctor: $this->m_wrapper=new Wrapper(); dtor: $this->m_wrapper->doWork(); is inherently unsafe, unless I totally got your message wrong (apologies for potential confusion). If you consider a common case such as the wrapper class wrapping a db connection or a file handle, and the client's destructor logging some "shutdown" message using that wrapper, I fail to realize how this would work with the given destructor scheme. I'm not too familiar with the old destruction scheme, but wouldn't a destruction scheme in which not all object destructors are called still be superior to one which is completely non-deterministic in terms of shutdown order? Or probably better, how about at least trying to shutdown in reverse creation order (and for all cases for which that won't work, use the new non-deterministic scheme)?
> [...]
Cheers, Michael PS: Apologies for obvious stupid remarks in this post, I'm sure I'm missing 1+ obvious issues

Zeev Suraski

22 years ago
At 23:45 04/02/2004, Andrei Zmievski wrote:
>On Wed, 04 Feb 2004, Andi Gutmans wrote: > > 3. The APIs have changed to allow for this new mechanism. Instead of the > > previous dtor callback, which was supposed to both call the destructor and > > free the object's storage, there are now two separate callbacks - dtor > > (call the destructor) and free_storage (guess). Generally, for classes > > which implement PHP-style objects, you should implement both of these > > callbacks (though you can probably use the standard dtor callback). For > > overloaded classes such as SimpleXML, COM, etc. - you will most likely > only > > have to implement the free_storage callback, as there's no destructor > > per-se. We already went over all the overloaded classes in the php-src > CVS > > and moved most of the dtor callbacks to free_storage. Note that the > > interface is slightly different between these two callbacks - free_storage > > doesn't receive the object handle. > >Is there an automatic call to __destruct() method then? Because I'd like >my PHP-GTK objects to have that method called upon destruction and I >don't feel like reimplementing the mechanism for doing that.
If it's a PHP-style object, then you can use zend_objects_destroy_object as your destructor callback (when calling zend_objects_store_put()), in which case __destruct() will be called. That's how the regular PHP objects do it. Zeev

Marcus Börger

22 years ago
Hello Zeev, Thursday, February 5, 2004, 12:24:47 AM, you wrote:
> At 23:45 04/02/2004, Andrei Zmievski wrote: >>On Wed, 04 Feb 2004, Andi Gutmans wrote: >> > 3. The APIs have changed to allow for this new mechanism. Instead of the >> > previous dtor callback, which was supposed to both call the destructor and >> > free the object's storage, there are now two separate callbacks - dtor >> > (call the destructor) and free_storage (guess). Generally, for classes >> > which implement PHP-style objects, you should implement both of these >> > callbacks (though you can probably use the standard dtor callback). For >> > overloaded classes such as SimpleXML, COM, etc. - you will most likely >> only >> > have to implement the free_storage callback, as there's no destructor >> > per-se. We already went over all the overloaded classes in the php-src >> CVS >> > and moved most of the dtor callbacks to free_storage. Note that the >> > interface is slightly different between these two callbacks - free_storage >> > doesn't receive the object handle. >> >>Is there an automatic call to __destruct() method then? Because I'd like >>my PHP-GTK objects to have that method called upon destruction and I >>don't feel like reimplementing the mechanism for doing that.
> If it's a PHP-style object, then you can use zend_objects_destroy_object as > your destructor callback (when calling zend_objects_store_put()), in which > case __destruct() will be called. That's how the regular PHP objects do it.
So my guess is that for most internal objects we need to do so?
-- Best regards, Marcus mailto:helly@php.net

Andi Gutmans

22 years ago
At 01:00 AM 2/5/2004 +0100, Marcus Boerger wrote:
> > If it's a PHP-style object, then you can use zend_objects_destroy_object as > > your destructor callback (when calling zend_objects_store_put()), in which > > case __destruct() will be called. That's how the regular PHP objects > do it. > >So my guess is that for most internal objects we need to do so?
Nope, I think most internal objects don't have destructors. This is only if the destructor is a PHP function not if it free's storage (which are most of the cases). So most internal objects will not have a destructor but will have a free storage function. Andi

Zeev Suraski

22 years ago
At 02:00 05/02/2004, Marcus Boerger wrote:
>Hello Zeev, > >Thursday, February 5, 2004, 12:24:47 AM, you wrote: > > > At 23:45 04/02/2004, Andrei Zmievski wrote: > >>On Wed, 04 Feb 2004, Andi Gutmans wrote: > >> > 3. The APIs have changed to allow for this new mechanism. Instead > of the > >> > previous dtor callback, which was supposed to both call the > destructor and > >> > free the object's storage, there are now two separate callbacks - dtor > >> > (call the destructor) and free_storage (guess). Generally, for classes > >> > which implement PHP-style objects, you should implement both of these > >> > callbacks (though you can probably use the standard dtor callback). For > >> > overloaded classes such as SimpleXML, COM, etc. - you will most likely > >> only > >> > have to implement the free_storage callback, as there's no destructor > >> > per-se. We already went over all the overloaded classes in the php-src > >> CVS > >> > and moved most of the dtor callbacks to free_storage. Note that the > >> > interface is slightly different between these two callbacks - > free_storage > >> > doesn't receive the object handle. > >> > >>Is there an automatic call to __destruct() method then? Because I'd like > >>my PHP-GTK objects to have that method called upon destruction and I > >>don't feel like reimplementing the mechanism for doing that. > > > If it's a PHP-style object, then you can use zend_objects_destroy_object as > > your destructor callback (when calling zend_objects_store_put()), in which > > case __destruct() will be called. That's how the regular PHP objects > do it. > >So my guess is that for most internal objects we need to do so?
Internal objects as in the ones in reflection and similar? Yes. But I'd imagine that for most other objects which completely overload the behavior, you wouldn't need that. Generally, if your object should be able to call __destruct() *AND* it's a PHP-style object (has the same structure), it should use that callback, otherwise - not. Be advised that your __destruct() mustn't actually render the object unusuable to the degree that PHP would crash if it touches it. It *may* be referenced after __destruct() is called (it would be an error on the author's part to do that, but nothing will prevent him from doing that). Zeev

Andrei Zmievski

22 years ago
On Thu, 05 Feb 2004, Zeev Suraski wrote:
> Internal objects as in the ones in reflection and similar? Yes. But I'd > imagine that for most other objects which completely overload the behavior, > you wouldn't need that. Generally, if your object should be able to call > __destruct() *AND* it's a PHP-style object (has the same structure), it > should use that callback, otherwise - not. > > Be advised that your __destruct() mustn't actually render the object > unusuable to the degree that PHP would crash if it touches it. It *may* be > referenced after __destruct() is called (it would be an error on the > author's part to do that, but nothing will prevent him from doing that).
So you are saying I can delegate calling __destruct() to Zend and then worry only about freeing storage in my objects? - Andrei

Zeev Suraski

22 years ago
At 23:16 05/02/2004, Andrei Zmievski wrote:
>On Thu, 05 Feb 2004, Zeev Suraski wrote: > > Internal objects as in the ones in reflection and similar? Yes. But I'd > > imagine that for most other objects which completely overload the > behavior, > > you wouldn't need that. Generally, if your object should be able to call > > __destruct() *AND* it's a PHP-style object (has the same structure), it > > should use that callback, otherwise - not. > > > > Be advised that your __destruct() mustn't actually render the object > > unusuable to the degree that PHP would crash if it touches it. It > *may* be > > referenced after __destruct() is called (it would be an error on the > > author's part to do that, but nothing will prevent him from doing that). > >So you are saying I can delegate calling __destruct() to Zend and then >worry only about freeing storage in my objects?
Yeah, assuming they're PHP-style objects (zend_object structure) then yes, it should work fine. Zeev

Red Wingate

22 years ago
Is the removal of a specific order on the __destruct() calls necessary? It's a pain in the ass the be unable to predict in which order the __destruct() calls are made. <?php     class my_error {         private $error_log = array();         function error_Register ( ... ) {             // register error to $this->error_log;         }         function __destruct () {             // Dump Error-Log to User ( E-Mail, HTML etc. )         }     }     class my_class {         // some code here         function __destruct () {             // trigger a error-msg         }     }     $my_error = new my_error();     set_error_handler( array( &$my_error , 'error_Register' ) );     $my_class = new my_class(); ?> In PHP 5 beta 3 even the error's thrown by my_class::__destruct() would be dumped by my_error::__destruct(), this won't work for the latest Snap.         Red

Stephane Drouard

22 years ago
== Quote from Red Wingate (redeye@erisx.de)'s article
> Is the removal of a specific order on the __destruct() calls > necessary? It's a pain in the ass the be unable to predict > in which order the __destruct() calls are made.
I did the following test: <? class C { function __construct($n) { $this->n = $n; } function __destruct() { print $this->n . '-'; } } for ($i = 0; $i < 10; $i++) $t[] = new C($i); $t[5]->o = $t[1]; // 5 should be deleted before 1 $t[8]->o = $t[5]; // 8 should be deleted before 5 (so 1) ?> The destruction order (0-1-2-3-4-5-6-7-8-9) does not respect the dependences. This is the current implementation. But when I execute the following: <? class C ... function f() { for ($i = 0; $i < 10; $i++) $t[] = new C($i); $t[5]->o = $t[1]; // 5 must be deleted before 1 $t[8]->o = $t[5]; // 8 must be deleted before 5 (and 1) } f(); ?> The result is '0-2-3-4-6-7-8-5-1-9', the objects are destroyed in an order that respects the dependences. If I now do a circular reference ($t[1]->o = $t[5]), these 2 objects (1 and 5) are not destroyed at the end of f(), like the others, but at the end of script (like global objects). Couldn't PHP implement global object destruction that way: * firstly try to destroyed them in the same way as for local variables (respecting dependences), * for objects that were not destroyed in the first step (certainly circular references), destroy them as currently implemented (no dependence check). A notice could also be displayed. Stephane

Michael Walter

22 years ago
Stephane Drouard wrote:
> == Quote from Red Wingate (redeye@erisx.de)'s article > >>Is the removal of a specific order on the __destruct() calls >>necessary? It's a pain in the ass the be unable to predict >>in which order the __destruct() calls are made. > [..] > Couldn't PHP implement global object destruction that way: > * firstly try to destroyed them in the same way as for local variables (respecting dependences), > * for objects that were not destroyed in the first step (certainly circular references), destroy them as currently implemented (no dependence check). A notice could also be displayed. >
Yeah, those both posts address exactly what my original post was referring to. Cheers, Michael

Adam Bregenzer

22 years ago
On Fri, 2004-02-06 at 06:01, Stephane Drouard wrote:
> Couldn't PHP implement global object destruction that way: > * firstly try to destroyed them in the same way as for local > variables (respecting dependences), > * for objects that were not destroyed in the first step (certainly > circular references), destroy them as currently implemented (no > dependence check). A notice could also be displayed.
+1 I think this is an excellent idea. Otherwise destructors have limited use. What is the plan for handling static variables in classes? Will a separate call be made to the destructor to handle these outside of any instance?
-- Adam Bregenzer adam@bregenzer.net http://adam.bregenzer.net/

Zeev Suraski

22 years ago
At 13:01 06/02/2004, Stephane Drouard wrote:
>== Quote from Red Wingate (redeye@erisx.de)'s article > > Is the removal of a specific order on the __destruct() calls > > necessary? It's a pain in the ass the be unable to predict > > in which order the __destruct() calls are made. > >I did the following test: > ><? >class C { > function __construct($n) { > $this->n = $n; > } > function __destruct() { > print $this->n . '-'; > } >} > >for ($i = 0; $i < 10; $i++) > $t[] = new C($i); >$t[5]->o = $t[1]; // 5 should be deleted before 1 >$t[8]->o = $t[5]; // 8 should be deleted before 5 (so 1) >?> > >The destruction order (0-1-2-3-4-5-6-7-8-9) does not respect the >dependences. This is the current implementation. > >But when I execute the following: > ><? >class C ... > >function f() { > for ($i = 0; $i < 10; $i++) > $t[] = new C($i); > $t[5]->o = $t[1]; // 5 must be deleted before 1 > $t[8]->o = $t[5]; // 8 must be deleted before 5 (and 1) >} >f(); >?> > >The result is '0-2-3-4-6-7-8-5-1-9', the objects are destroyed in an order >that respects the dependences. > >If I now do a circular reference ($t[1]->o = $t[5]), these 2 objects (1 >and 5) are not destroyed at the end of f(), like the others, but at the >end of script (like global objects). > >Couldn't PHP implement global object destruction that way: > * firstly try to destroyed them in the same way as for local variables > (respecting dependences), > * for objects that were not destroyed in the first step (certainly > circular references), destroy them as currently implemented (no > dependence check). A notice could also be displayed.
To make a long story short, no. Circular references are hardly the problem, even a one-sided reference can be problematic. Just one example (there are many others) - you have $container and $obj, both are global variables, $container has a reference to $obj and uses it during destruction. Voila, you have a problem - you have to somehow ensure that $obj's destructor is called only after $container's destructor. Yes, I agree it's somewhat of a pain, but that's the price of getting destructors in the first place. It may be one of the reasons destructors never made it into Java. I have to say that introducing them into PHP was most probably a mistake, but one that we'll have to live with due to popular demand. Zeev

Michael Walter

22 years ago
Zeev Suraski wrote:
> At 13:01 06/02/2004, Stephane Drouard wrote: > >> == Quote from Red Wingate (redeye@erisx.de)'s article >> > Is the removal of a specific order on the __destruct() calls >> > necessary? It's a pain in the ass the be unable to predict >> > in which order the __destruct() calls are made. >> >> I did the following test: >> >> <? >> class C { >> function __construct($n) { >> $this->n = $n; >> } >> function __destruct() { >> print $this->n . '-'; >> } >> } >> >> for ($i = 0; $i < 10; $i++) >> $t[] = new C($i); >> $t[5]->o = $t[1]; // 5 should be deleted before 1 >> $t[8]->o = $t[5]; // 8 should be deleted before 5 (so 1) >> ?> >> >> The destruction order (0-1-2-3-4-5-6-7-8-9) does not respect the >> dependences. This is the current implementation. >> >> But when I execute the following: >> >> <? >> class C ... >> >> function f() { >> for ($i = 0; $i < 10; $i++) >> $t[] = new C($i); >> $t[5]->o = $t[1]; // 5 must be deleted before 1 >> $t[8]->o = $t[5]; // 8 must be deleted before 5 (and 1) >> } >> f(); >> ?> >> >> The result is '0-2-3-4-6-7-8-5-1-9', the objects are destroyed in an >> order that respects the dependences. >> >> If I now do a circular reference ($t[1]->o = $t[5]), these 2 objects >> (1 and 5) are not destroyed at the end of f(), like the others, but at >> the end of script (like global objects). >> >> Couldn't PHP implement global object destruction that way: >> * firstly try to destroyed them in the same way as for local >> variables (respecting dependences), >> * for objects that were not destroyed in the first step (certainly >> circular references), destroy them as currently implemented (no >> dependence check). A notice could also be displayed. > > > To make a long story short, no. Circular references are hardly the > problem, even a one-sided reference can be problematic. Just one > example (there are many others) - you have $container and $obj, both are > global variables, $container has a reference to $obj and uses it during > destruction. Voila, you have a problem - you have to somehow ensure > that $obj's destructor is called only after $container's destructor.
Usually, it is sufficient to deconstruct in reverse construction order in this case: $obj=PLA; $container=...; Hence, destruction order is $container, $obj -- no problem (unless you're dealing with circular references, which actually are the problem I think). Cheers, Michael

Zeev Suraski

22 years ago
At 22:19 06/02/2004, Michael Walter wrote:
>Usually, it is sufficient to deconstruct in reverse construction order in >this case: > >$obj=PLA; >$container=...; > >Hence, destruction order is $container, $obj -- no problem (unless you're >dealing with circular references, which actually are the problem I think).
Yeah, but 'usually' doesn't cut it... If someone does $container=...; $obj = $container->getFoo(); then you're screwed with that solution. And it's not as if it's that rare... Zeev

Zeev Suraski

22 years ago
At 00:58 07/02/2004, Christian Jerono wrote:
>Well so wouldn't 'reverse construction order' mean: >$container=...; >$obj = $container->getFoo(); >results in call of $obj->__destruct(); and then $container->__destruct(); >maybe i just missed the problem here?
Yes, and yes you did :) The whole problem is if $container needs to use Foo, its element, during destruction. Zeev

Michael Walter

22 years ago
Zeev Suraski wrote:
> At 00:58 07/02/2004, Christian Jerono wrote: > >> Well so wouldn't 'reverse construction order' mean: >> $container=...; >> $obj = $container->getFoo(); >> results in call of $obj->__destruct(); and then $container->__destruct(); >> maybe i just missed the problem here? > > > Yes, and yes you did :) The whole problem is if $container needs to use > Foo, its element, during destruction.
Well, the $obj reference would be "freed" first (--refcount), then all left would be $container (which still holds a reference to its $m_foo data member). Without having circular references and stuff, it should be possible to clean up the data members of a particular instance after the corresponding destructor call, I suppose. Cheers, Michael

Stephane Drouard

22 years ago
== Quote from Zeev Suraski (zeev@zend.com)'s article
> To make a long story short, no. Circular references are hardly the > problem, even a one-sided reference can be problematic. Just one example > (there are many others) - you have $container and $obj, both are global > variables, $container has a reference to $obj and uses it during > destruction. Voila, you have a problem - you have to somehow ensure that > $obj's destructor is called only after $container's destructor.
Zeev, There's something I don't understand: destruction order respects dependences when existing functions (except for circular references, but it's normal). So why does it seem so complicated to implement the same mechanism for global variables at a first step? This would resolve all the non-circular references. And then, in an unpredictable order for remaining variables. Regards, Stephane

Zeev Suraski

22 years ago
At 12:03 07/02/2004, Stephane Drouard wrote:
>== Quote from Zeev Suraski (zeev@zend.com)'s article > > To make a long story short, no. Circular references are hardly the > > problem, even a one-sided reference can be problematic. Just one example > > (there are many others) - you have $container and $obj, both are global > > variables, $container has a reference to $obj and uses it during > > destruction. Voila, you have a problem - you have to somehow ensure that > > $obj's destructor is called only after $container's destructor. > >Zeev, > >There's something I don't understand: destruction order respects >dependences when existing functions (except for circular references, but >it's normal).
Depends on what you're talking about when you mention destruction order. Generally, there's no order in anything in PHP, because it's based on hashes. We sometimes use the term reverse-destruction because somewhere in there there's also a linked list that tends to have some particular order, but again, it takes less than 5 minutes to come up with a test case that shows that it's not really ordered after all. If you're talking about destruction that honors reference counts (which has nothing to do with order, it's still randomly-ordered), then yes, it's *generally* ok. But that what we had before, and it had tons of problems. For instance, do you want to give up the ability to access the symbol table (e.g. $GLOBALS) from destructors? Because the symtable elements won't have anything to protect them from being deleted, their refcount is 1. Just in case you're willing to live without it, it did use to be that way, and people did complain :) Generally, you can really forget about a 'silver bullet' approach when it comes to destructors. There's no perfect way of doing it, at least not one that's practical to implement within reasonable constraints. And frankly, it's not that much of a problem anyway. PHP users, for some reason, enjoy abusing language features, and use them for things they shouldn't be used for. Destructors should be used for destruction, not logic. If your object contains other objects with resources, their destructors should free them, and these object shouldn't be touched during the destruction of their container. While it may be possible to find some valid usages for using member objects during destruction, it's not much of a big deal to live without it. Zeev

Stephane Drouard

22 years ago
== Quote from Zeev Suraski (zeev@zend.com)'s article
> If you're talking about destruction that honors reference counts (which has > nothing to do with order, it's still randomly-ordered), then yes, it's > *generally* ok.
Yes, I was talking about that point.
> But that what we had before, and it had tons of > problems. For instance, do you want to give up the ability to access the > symbol table (e.g. $GLOBALS) from destructors? Because the symtable > elements won't have anything to protect them from being deleted, their > refcount is 1. Just in case you're willing to live without it, it did use > to be that way, and people did complain :)
Do you mean that global variables have their refcount "locked to 1", or "never less than 1"? For sure if they are "locked to 1", I now understand why destruction of such objects can't reflect "dependences". Stephane

Zeev Suraski

22 years ago
At 12:38 09/02/2004, Stephane Drouard wrote:
>== Quote from Zeev Suraski (zeev@zend.com)'s article > > If you're talking about destruction that honors reference counts (which has > > nothing to do with order, it's still randomly-ordered), then yes, it's > > *generally* ok. > >Yes, I was talking about that point. > > > But that what we had before, and it had tons of > > problems. For instance, do you want to give up the ability to access the > > symbol table (e.g. $GLOBALS) from destructors? Because the symtable > > elements won't have anything to protect them from being deleted, their > > refcount is 1. Just in case you're willing to live without it, it did use > > to be that way, and people did complain :) > >Do you mean that global variables have their refcount "locked to 1", or >"never less than 1"? > >For sure if they are "locked to 1", I now understand why destruction of >such objects can't reflect "dependences".
They're not locked to 1, and nothing in a symbol table will ever be with a refcount of less than 1... But generally, all global variables (or for that matter, all variables period) have a refcount of 1, unless you do something 'special'. Zeev

Stephane Drouard

22 years ago
== Quote from Zeev Suraski (zeev@zend.com)'s article
> They're not locked to 1, and nothing in a symbol table will ever be with a > refcount of less than 1... But generally, all global variables (or for > that matter, all variables period) have a refcount of 1, unless you do > something 'special'.
Right. So if a global variable "father" owns a reference to another global variable "child", I assume "child"'s refcount is higher than "father"'s one, let's say 2 for "child" ($GLOBALS + "father") and 1 for "father" ($GLOBALS), assuming they are not referenced elsewhere. So why PHP can't guaranty that "father"'s destructor is called before "child"'s one? Stephane

Andi Gutmans

22 years ago
At 01:36 PM 2/9/2004 +0000, Stephane Drouard wrote:
>== Quote from Zeev Suraski (zeev@zend.com)'s article > > They're not locked to 1, and nothing in a symbol table will ever be with a > > refcount of less than 1... But generally, all global variables (or for > > that matter, all variables period) have a refcount of 1, unless you do > > something 'special'. > >Right. So if a global variable "father" owns a reference to another global >variable "child", I assume "child"'s refcount is higher than "father"'s >one, let's say 2 for "child" ($GLOBALS + "father") and 1 for "father" >($GLOBALS), assuming they are not referenced elsewhere. >So why PHP can't guaranty that "father"'s destructor is called before >"child"'s one?
He doesn't necessarily own a reference but tries to access it in the destructor. Andi

Stephane Drouard

22 years ago
== Quote from Andi Gutmans (andi@zend.com)'s article
> He doesn't necessarily own a reference but tries to access it in the > destructor.
IMO, this is bad programming. If an object wants to access another object (global or not), it has to own a reference on it, to guaranty the referenced object will be destroyed afterwards (so including destructor). Stephane

Andi Gutmans

22 years ago
At 03:55 PM 2/9/2004 +0000, Stephane Drouard wrote:
>== Quote from Andi Gutmans (andi@zend.com)'s article > > He doesn't necessarily own a reference but tries to access it in the > > destructor. > >IMO, this is bad programming. If an object wants to access another object >(global or not), it has to own a reference on it, to guaranty the >referenced object will be destroyed afterwards (so including destructor).
You are getting into coding style now. The bottom line is that there are lots of different ways of writing code and many ppl do different stuff and often odd stuff. We think the solution that exists today is most likely to suit the largest amount of PHP users. The same way you are complaining ppl will complain if they can't access $GLOBALS[] from the destructor. Andi

Andrei Zmievski

22 years ago
On Fri, 06 Feb 2004, Zeev Suraski wrote:
> Yeah, assuming they're PHP-style objects (zend_object structure) then yes, > it should work fine.
Well, they look something like: typedef struct { zend_object zobj; void *p; dtor_t dtor; } my_object; - Andrei