PHP & Reference Counting

windows

Guest
Basically, I am a little confused about reference counting in php.

I created a simple singleton class and then pass the singleton object to two other classes.. I would think that there would be two references of the singleton object in the test objects, which would not allow the singleton to destruct until the references are unlinked.

Here are my results..

DESTRUCT TEST REFERENCE
DESTRUCT SINGLETON
DESTRUCT TEST REFERENCE

From my understanding of references, this is what I would assume the output should be..

DESTRUCT TEST REFERENCE
DESTRUCT TEST REFERENCE
DESTRUCT SINGLETON

Here is the code below.


class test_singleton {
private static $instance = NULL;

private function __construct() {
echo("CONSTRUCT SINGLETON<br>");
}

public function __destruct() {
echo("DESTRUCT SINGLETON<br>");
}

public static function getinstance() {
if (is_null(self::$instance)) {
self::$instance = new test_singleton();
}

return self::$instance;
}
}

class test_references {
private $test = NULL;

public function __construct() {
echo("CONSTRUCT TEST REFERENCE<br>");

$this->test = test_singleton::getinstance();
}

public function __destruct() {
echo("DESTRUCT TEST REFERENCE<br>");
}
}

$test1 = new test_references();
$test2 = new test_references();

//unset($test1,$test2);


If anyone could explain why this happens this way.. it would be great and maybe a solution to produce these results?Why should the second order of destruction be any more likely than the first? You never explicitly say the objects should be destroyed in that order.

For performance and reliability reasons (think circular references), PHP suspends the usual reference-counting rules and just walks down its list of instantiated objects and calls each destruct method one after the other - in the order that they were instantiated, as it happens, hence the order you observe.

Note that calling __destruct() doesn't actually destroy the object - that's not what it's for - so objects that reference other objects in their __destruct() method won't suddenly find them arbitrarily absent.
 
Back
Top