Re: [PHP] unset and circular references
Quoting Abu Warez [EMAIL PROTECTED]: Hi, I'm using php 5.2.1 on an Ubuntu machine. I have the following class diagram (observer pattern): +-+ +-+ +-+ | class A |#-| class B | -| interface C | | | +-+ | | | |---|| | +-+ +-+ in my case class A, the creator of class B, is also the class to observe for class B. The following code implements the above diagram: ?php interface C { } class B { var $m_ObsC; public function __construct( C $p_ObsC ) { $this-m_ObsC = $p_ObsC; } public function __destruct() { echo B::destruct called br; } } class A implements C { var $m_b; public function __construct() { $this-m_b = new B( $this ); } public function __destruct() { echo A::destruct called br; } } $a = new A(); unset( $a ); echo br-end-of-scriptbr; ? the output of the above code is: -end-of-script A::destruct called B::destruct called So actually the memory used by object $a is freed only after the script ends and NOT when unset was called. Now this is a big problem for me, because i need to free the memory when I call unset and not after the script ends else php runs out of memory in my real application. Object $a is not referenced by any other object. I also tried with: $this-m_b = new B( $this ); but the result is the same. Any clue how to determine php tho free the memory when unset is called and not after the script ends? Thanks, Abu I think this happens because there is still a reference to the B object. According to the manual : The destructor method will be called as soon as all references to a particular object are removed or when the object is explicitly destroyed or in any order in shutdown sequence. So as long as A has a reference to B the __destructor will not be called. -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] unset and circular references
--- On Fri, 6/27/08, Thijs Lensselink [EMAIL PROTECTED] wrote: From: Thijs Lensselink [EMAIL PROTECTED] Subject: Re: [PHP] unset and circular references To: php-general@lists.php.net Date: Friday, June 27, 2008, 5:21 PM Quoting Abu Warez [EMAIL PROTECTED]: Hi, I'm using php 5.2.1 on an Ubuntu machine. I have the following class diagram (observer pattern): +-+ +-+ +-+ | class A |#-| class B | -| interface C | | | +-+ | | | |---|| | +-+ +-+ in my case class A, the creator of class B, is also the class to observe for class B. The following code implements the above diagram: ?php interface C { } class B { var $m_ObsC; public function __construct( C $p_ObsC ) { $this-m_ObsC = $p_ObsC; } public function __destruct() { echo B::destruct called br; } } class A implements C { var $m_b; public function __construct() { $this-m_b = new B( $this ); } public function __destruct() { echo A::destruct called br; } } $a = new A(); unset( $a ); echo br-end-of-scriptbr; ? the output of the above code is: -end-of-script A::destruct called B::destruct called So actually the memory used by object $a is freed only after the script ends and NOT when unset was called. Now this is a big problem for me, because i need to free the memory when I call unset and not after the script ends else php runs out of memory in my real application. Object $a is not referenced by any other object. I also tried with: $this-m_b = new B( $this ); but the result is the same. Any clue how to determine php tho free the memory when unset is called and not after the script ends? Thanks, Abu I think this happens because there is still a reference to the B object. According to the manual : The destructor method will be called as soon as all references to a particular object are removed or when the object is explicitly destroyed or in any order in shutdown sequence. So as long as A has a reference to B the __destructor will not be called. -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] unset and circular references
--- On Fri, 6/27/08, Thijs Lensselink [EMAIL PROTECTED] wrote: From: Thijs Lensselink [EMAIL PROTECTED] Subject: Re: [PHP] unset and circular references To: php-general@lists.php.net Date: Friday, June 27, 2008, 5:21 PM Quoting Abu Warez [EMAIL PROTECTED]: I think this happens because there is still a reference to the B object. According to the manual : The destructor method will be called as soon as all references to a particular object are removed or when the object is explicitly destroyed or in any order in shutdown sequence. So as long as A has a reference to B the __destructor will not be called. I think you mean: As long as B has a ref to A (which, indeed, creates B), the destructor of A will not be called. I agree with that, but in this case the garbage collector should detect that the reference to object $a is from an object $m_b which is created (and maintained) again by the first object $a. In other words, if object $a is not needed then its member $m_b (which has a reference to $a) is not needed neither. So in this case, in my opinion, if one wants to destory object $a then the reference from $m_b to $a should not count. This issue is really frustrating because because in my code I have something like (where $a is of type class A): for ( $id ... ) { $a = daoMyClass-LoadById( $id ); modify $a ... /* persist modified $a */ daoMyClass-Update( $a ); unset( $a ); } unset, as stated, does not destroy $a and all the loaded $a's remain in memory until the script ends. Rising the memory limit is not a solution because the count of $a objects grows between script calls. Any ideas? Thx, Abu -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] unset and circular references
Abu Warez wrote: --- On Fri, 6/27/08, Thijs Lensselink [EMAIL PROTECTED] wrote: From: Thijs Lensselink [EMAIL PROTECTED] Subject: Re: [PHP] unset and circular references To: php-general@lists.php.net Date: Friday, June 27, 2008, 5:21 PM Quoting Abu Warez [EMAIL PROTECTED]: I think this happens because there is still a reference to the B object. According to the manual : The destructor method will be called as soon as all references to a particular object are removed or when the object is explicitly destroyed or in any order in shutdown sequence. So as long as A has a reference to B the __destructor will not be called. I think you mean: As long as B has a ref to A (which, indeed, creates B), the destructor of A will not be called. My bad. that's what i meant. I agree with that, but in this case the garbage collector should detect that the reference to object $a is from an object $m_b which is created (and maintained) again by the first object $a. In other words, if object $a is not needed then its member $m_b (which has a reference to $a) is not needed neither. So in this case, in my opinion, if one wants to destory object $a then the reference from $m_b to $a should not count. That would still leave a reference from B to A. That's why it doesn't get unset. If you unset B before unsetting A the problem is resolved. This issue is really frustrating because because in my code I have something like (where $a is of type class A): for ( $id ... ) { $a = daoMyClass-LoadById( $id ); modify $a ... /* persist modified $a */ daoMyClass-Update( $a ); unset( $a ); } unset, as stated, does not destroy $a and all the loaded $a's remain in memory until the script ends. Rising the memory limit is not a solution because the count of $a objects grows between script calls. Any ideas? Thx, Abu -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php