zval通過引用計數(shù)來節(jié)省內(nèi)存的,這個我們都知道了,但你可能不知道的是,某個zval對應(yīng)的{資源}在實現(xiàn)時也使用了引用計數(shù)這種概念,也就是有了兩種引用計數(shù)!
{資源}對應(yīng)的zval的類型是IS_RESOURCE,它并不保存最終的數(shù)據(jù),而只保存一個數(shù)字,即EG(regular_list)中的數(shù)字索引。
當(dāng){資源}被創(chuàng)建時,比如我們調(diào)用sample_fopen()函數(shù):
$a = sample_fopen('notes.txt', 'r');
//此時:var->refcount__gc = 1, rsrc->refcount = 1
$b = $a;
//此時:var->refcount__gc = 2, rsrc->refcount = 1
unset($b);
//此時:var->refcount__gc = 1, rsrc->refcount = 1
/*
下面來個復(fù)雜的!
*/
$b = $a;
$c = &$a;
//此時:
/*
bvar->refcount = 1, bvar->is_ref = 0
acvar->refcount = 2, acvar->is_ref = 1
rsrc->refcount = 2
*/
現(xiàn)在,如果我們unset($b),內(nèi)核只會把rsrc->refcount的值減1。只有當(dāng)rsrc->refcount的值為0時,我們預(yù)設(shè)的dtor釋放函數(shù)才會被激活并調(diào)用。