ファイバー(PHP 8.1)
CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 60/91。
Fibers は、割り込み可能なコード実行を実現する PHP 8.1 の機能です。最初から最後まで実行される通常の関数とは異なり、fiber は実行途中で自身を一時停止し、後で再開できます。また、一時停止の間も状態を維持します。
Fiberクラスにcallableを渡してファイバーを作成し、start()で開始します:
<?php
$fiber = new Fiber(function(): void {
echo "Step 1\n";
Fiber::suspend();
echo "Step 2\n";
});
$fiber->start();
echo "Between steps\n";
$fiber->resume();
出力:
Step 1
Between steps
Step 2ファイバーは Fiber::suspend() に到達するまで実行され、その後、制御がメインコードに戻ります。resume() を呼び出すと、一時停止した場所から実行が再開されます。
Fiberは、一時停止および再開時に値を渡すこともできます。
<?php
$fiber = new Fiber(function(): string {
$value = Fiber::suspend("paused");
return "Received: $value";
});
$suspended = $fiber->start();
echo "$suspended\n";
$result = $fiber->resume("hello");
echo $result;
出力:
paused
Received: helloファイバーは、非同期 PHP フレームワークの基盤です。ほとんどのアプリケーションで直接使うことはありませんが、ブロックせずに HTTP リクエストやデータベースクエリなどの同時実行操作を処理する非同期ライブラリを扱う際に、ファイバーを理解していると役立ちます。
チャレンジ
簡単fiber とメインコードの間でデータを渡しながら、fiber が実行を一時停止および再開できることを示すタスクスケジューラーを構築しましょう。タスクを中断して、その間に別の処理を実行できるシステムを作成します。
コードを2つのファイルに分けて整理します。
TaskRunner.php: タスクを実行するための fiber 機能をラップするTaskRunnerclass を作成します。class には次の機能を持たせます。Fiberインスタンスを保存する private プロパティを持つ- コンストラクターのプロモーションを使用して、コンストラクターでタスク名(string)を受け取る
- 指定された callable で新しい Fiber を作成し、それを保存する
createTask(callable $task)メソッドを持つ - fiber を開始し、fiber が一時停止した際の値(または最終的な戻り値)を返す
start()メソッドを持つ - 指定された値で fiber を再開し、次に一時停止した値(または最終的な戻り値)を返す
continue(mixed $value)メソッドを持つ - fiber が終了しているかどうかを返す
isFinished(): boolメソッドを持つ
main.php: TaskRunner ファイルをインクルードします。2つの input、つまりタスク名と fiber に送る message を受け取ります。指定されたタスク名で
TaskRunnerを作成し、次にcreateTask()を使用して次の処理を行うタスクを define します。- まず、文字列
"Waiting for input"で一時停止する - resumed したときに値を Receives する
"Completed: [received value]"を返す
タスクを開始し、最初に一時停止したときに返される値を print します。次に、fiber の一時停止の between で処理が行われていることを示すため、
"Processing..."を print します。最後に、message input を渡して fiber を continue し、最終結果を print します。- まず、文字列
この challenge は、fiber によって協調的マルチタスクが可能になることを示します。タスクは都合のよい時点で自らを一時停止し、メインコードが別の処理を行った後、新しいデータでタスクを再開します。fiber はその間ずっと状態を維持し、pauses した地点から正確に処理を再開します。
自分で試してみよう
<?php
require_once 'TaskRunner.php';
// 入力を読み取る
$taskName = trim(fgets(STDIN));
$message = trim(fgets(STDIN));
// TODO: 指定されたタスク名で TaskRunner を作成する
// TODO: createTask() を使用して次のようなタスクを定義する:
// 1. First suspends with the string "Waiting for input"
// 2. 再開時に値を受け取る
// 3. "Completed: [received value]" を返す
// TODO: タスクを開始し、最初に中断したときに返す内容を出力する
// TODO: ファイバーの一時停止の間に作業が行われていることを示すために "Processing..." を出力する
// TODO: メッセージ入力を渡してファイバーを続行する
// TODO: 最終結果を出力する
?>このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: PHPオンラインコンパイラ