Обзор файберов
(PHP 8 >= 8.1.0)
Файберы — механизм управления функциями, который умеет прерывать выполнение функций с сохранением полного внутреннего стека вызовов.
Файберы разрешается приостанавливать в произвольном месте внутреннего стека вызовов, при этом выполнение кода внутри файбера
приостанавливается, пока файбер не возобновит работу.
Файберы приостанавливают весь внутренний стек выполнения, поэтому коду, который работает с файберами,
не придётся изменять логику вызова методов файбера (тогда как в других языках программирования
при взаимодействии с асинхронными сопрограммами вызывающий код вынужденно изменяет способ вызова функций — прим. перев.).
Выполнение файбера разрешается прерывать методом Fiber::suspend() в произвольном месте стека вызовов,
вызвать метод Fiber::suspend() можно в глубоко вложенной функции
или не вызывать вовсе.
В отличие от бесстековых Generator'ов, под каждый Fiber
внутренне выделяется отдельный стек вызовов, что разрешает приостанавливать стеки внутри глубоко вложенных вызовов функций.
Функция, которая вызовом метода Fiber::suspend() объявляет точку прерывания файбера,
не изменяет тип значения, которое она возвращает, в отличие от функций, которые содержат ключевое слово yield
и потому возвращают экземпляр класса Generator.
Приостановка файберов доступна как в пользовательских функциях, так и в функциях,
которые вызываются внутри виртуальной машины языка PHP, наподобие callback-функции,
которую передают как аргумент функции array_map(), или методов, которые цикл foreach
вызывает на объекте класса Iterator.
Выполнение приостановленного файбера возобновляют либо вызовом метода Fiber::resume(),
который умеет передавать в точку приостановки файбера произвольное значение, либо вызовом метода Fiber::throw(),
который передаёт исключение в ту же точку. При возобновлении работы файбера с передачей значения это значение
возвращается в точке прерывания файбера как результат вызова метода Fiber::suspend(),
а при передаче исключения — файбер возобновляет выполнение в той же точке и выбрасывает это исключение.
Замечание:
До PHP 8.4.0 запрещалось переключать файбер в деструкторе объекта.
Пример #1 Стандартный пример работы с файбером
<?php
$fiber = new Fiber(function (): void {
$value = Fiber::suspend('fiber');
echo "Значение возобновлённого файбера: ", $value, PHP_EOL;
});
$value = $fiber->start();
echo "Значение приостановленного файбера: ", $value, PHP_EOL;
$fiber->resume('test');
?>
Результат выполнения приведённого примера:
Значение приостановленного файбера: fiber
Значение возобновлённого файбера: test