Простой вопрос
Когда или как сами PHP или генераторы уничтожают свои стеки?
Возьмите следующий пример:
function doWork(): Generator
{
// create some objects.
$o1 = new stdClass();
$o2 = new stdClass();
// pause here and wait for data.
$value = yield 1;
// By referencing the above objects, they shouldn't destruct.
$o1->property = $value;
$o2->property = $value;
yield $o1;
yield $o2;
// End of stack.
}
// Create the generator.
$generator = doWork();
$value = $generator->current(); // $value will equal 1.
if ($x) {
$generator->send('Hello, World!'); // Continue execution of the generator.
$o1 = $generator->current();
$generator->next();
$o2 = $generator->current();
$generator->next(); // Complete the generator
var_dump($o1);
var_dump($o2);
} else {
// Do nothing with the generator.
}
// Carry on with script ...
В этом примере запускается генератор и создаются два объекта. В этот момент он получен, и запрашиваются дополнительные данные.
Заявление IF достигнуто.
Случай 1
Если $x
верно, значение "Hello, World!"
будет отправлен в генератор, и объекты будут заполнены их новыми свойствами.
При следующем прочтении полученных данных объекты будут возвращены.
Дело 2
Если $x
Значение false, генератор больше не будет использоваться.
Вопрос
В случае 1 я бы ожидал, что стек закроется, как и любая другая функция, но что происходит с генератором в случае 2? Он и все оставшиеся ссылки на объекты остаются в памяти, пока сценарий не завершится?
Или потеря ссылки на $generator
вызвать это, и все ссылки внутри должны быть очищены?
Есть два условия, при которых генератор разрушает свой контекст выполнения (который также включает таблицу переменных):
return
(включая неявный возврат в конце функции) или через необработанное исключение во время выполнения генератора.Так что нет, генератор не будет жить, пока не закончится сценарий. Он будет уничтожен, как только $generator
переменная выходит из области видимости, после чего генератор откажется от своих ссылок на значения переменной и другое состояние выполнения.
Вы можете легко наблюдать за порядком уничтожения, создав класс, который echo
s в деструкторе, а затем создать экземпляр этого класса в локальной переменной.
Других решений пока нет …