Fibers

Обзор файберов

(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