ReactPHP のコア リアクター イベント ループ。ライブラリはイベント I/O に使用できます。
開発バージョン:このブランチには、今後の v3 リリースのコードが含まれています。現在の安定版 v1 リリースのコードについては、
1.x
ブランチをチェックしてください。今後の v3 リリースがこのパッケージの前進となります。ただし、まだ最新バージョンを使用していないユーザーのために、引き続き v1 を積極的にサポートします。詳細については、インストール手順も参照してください。
非同期ベースのライブラリを相互運用するには、同じイベント ループを使用する必要があります。このコンポーネントは、あらゆるライブラリがターゲットにできる共通のLoopInterface
を提供します。これにより、ユーザーが制御する 1 つのrun()
呼び出しで、同じループ内でそれらを使用できるようになります。
目次
クイックスタートの例
使用法
走る()
停止()
addTimer()
addPeriodicTimer()
キャンセルタイマー()
futureTick()
addSignal()
削除シグナル()
addReadStream()
addWriteStream()
削除ReadStream()
削除書き込みストリーム()
ストリーム選択ループ
ExtEventLoop
ExtEvLoop
ExtUvLoop
ループメソッド
ループの自動実行
得る()
ループ
ループの実装
ループインターフェース
インストール
テスト
ライセンス
もっと
以下は、イベント ループのみで構築された非同期 HTTP サーバーです。
<?phpuse ReactEventLoopLoop;require __DIR__ 。 '/vendor/autoload.php';$server = stream_socket_server('tcp://127.0.0.1:8080');stream_set_blocking($server, false); Loop::addReadStream($server, function ($server) {$conn = stream_socket_accept($server);$data = "HTTP/1.1 200 OKrnContent-Length: 3rnrnHin"; Loop::addWriteStream($conn, function ($conn) use (&$data) {$write = fwrite($conn, $data);if ($write === strlen($data)) {fclose($conn) ); Loop::removeWriteStream($conn); } else {$data = substr($data, $write); } }); }); Loop::addPeriodicTimer(5, function () {$memory =memory_get_usage() / 1024;$formatted =number_format($memory, 3).'K';echo "現在のメモリ使用量: {$formatted}n"; });
例も参照してください。
一般的なアプリケーションでは、次のようにLoop
クラスを使用してデフォルトのイベント ループを使用します。
ReactEventLoopLoop;$timer = Loop::addPeriodicTimer(0.1, function () {echo 'Tick' . PHP_EOL; を使用します。 }); Loop::addTimer(1.0, function () use ($timer) { Loop::cancelTimer($timer);echo 'Done' 。 PHP_EOL; });
別の方法として、次のように最初にイベント ループ インスタンスを明示的に作成し、それをプログラム全体で再利用し、最後にプログラムの最後で実行することもできます。
$loop = ReactEventLoopLoop::get();$timer = $loop->addPeriodicTimer(0.1, function () {echo 'Tick' . PHP_EOL; });$loop->addTimer(1.0, function () use ($loop, $timer) {$loop->cancelTimer($timer);echo 'Done' . PHP_EOL; });$loop->run();
前者はより簡潔ですが、後者はより明確です。どちらの場合も、プログラムはまったく同じ手順を実行します。
イベント ループ インスタンスはプログラムの先頭で作成されます。これは、 Loop
クラスを初めて呼び出すときに (またはループ実装のいずれかを手動でインスタンス化することによって) 暗黙的に行われます。
イベント ループは直接使用されるか、インスタンスとしてライブラリおよびアプリケーション コードに渡されます。この例では、周期タイマーがイベント ループに登録されており、1 秒後に別のタイマーが周期タイマーを停止するまで、単純に 1 秒ごとにTick
を出力します。
イベントループはプログラムの最後に実行されます。これは、 Loop
クラスを使用する場合、またはプログラムの最後に 1 回のrun()
呼び出しを使用して明示的に行われるときに自動的に行われます。
v1.2.0
の時点では、 Loop
クラスの使用を強くお勧めします。明示的なループ命令は依然として有効であり、一部のアプリケーション、特により簡潔なスタイルへの移行期間では依然として役立つ可能性があります。
Loop
クラスは、イベント ループの便利なグローバル アクセサーとして存在します。
Loop
クラスは、 LoopInterface
に存在するすべてのメソッドを静的メソッドとして提供します。
走る()
停止()
addTimer()
addPeriodicTimer()
キャンセルタイマー()
futureTick()
addSignal()
削除シグナル()
addReadStream()
addWriteStream()
削除ReadStream()
削除書き込みストリーム()
アプリケーション コードでイベント ループを使用している場合は、多くの場合、次のようにLoop
クラスで定義された静的メソッドと直接インターフェイスするのが最も簡単です。
ReactEventLoopLoop;$timer = Loop::addPeriodicTimer(0.1, function () {echo 'Tick' . PHP_EOL; を使用します。 }); Loop::addTimer(1.0, function () use ($timer) { Loop::cancelTimer($timer);echo 'Done' 。 PHP_EOL; });
一方、オブジェクト指向プログラミング (OOP) や依存関係注入 (DI) に精通している場合は、次のようにイベント ループ インスタンスを挿入し、 LoopInterface
でインスタンス メソッドを呼び出すこともできます。
ReactEventLoopLoop を使用する;ReactEventLoopLoopInterface を使用する;クラス Greeter {プライベート $ループ;パブリック関数 __construct(LoopInterface $loop) {$this->loop = $loop; }パブリック関数greet(string $name) {$this->loop->addTimer(1.0, function () use ($name) {echo 'Hello ' . $name . '!' . PHP_EOL; }); } }$greeter = new Greeter(Loop::get());$greeter->greet('Alice');$greeter->greet('Bob');
各静的メソッド呼び出しは、内部でLoop::get()
呼び出しを使用することにより、基になるイベント ループ インスタンスにそのまま転送されます。使用可能なメソッドの詳細については、 LoopInterface
参照してください。
Loop
クラスを使用すると、プログラムの最後にループが自動的に実行されます。これは、次の例ではタイマーをスケジュールし、タイマー イベントが発生するまでプログラムを自動的に実行することを意味します。
ReactEventLoopLoop を使用します。 Loop::addTimer(1.0, function () {echo 'Hello' . PHP_EOL; });
v1.2.0
の時点では、この方法でLoop
クラスを使用し、明示的なrun()
呼び出しを省略することを強くお勧めします。 BC の理由により、明示的なrun()
メソッドは依然として有効であり、一部のアプリケーション、特により簡潔なスタイルへの移行期間では依然として役立つ可能性があります。
Loop
自動的に実行したくない場合は、明示的にrun()
またはstop()
ことができます。これは、次のようなグローバル例外ハンドラーを使用している場合に便利です。
ReactEventLoopLoop を使用します。 Loop::addTimer(10.0, function () {echo '決して起こらない'; });set_Exception_handler(function (Throwable $e) {echo 'エラー: ' . $e->getMessage() . PHP_EOL; ループ::ストップ(); });新しい RuntimeException('Demo') をスローします。
get(): LoopInterface
メソッドを使用して、現在アクティブなイベント ループ インスタンスを取得できます。
このメソッドは、アプリケーションの存続期間中、常に同じイベント ループ インスタンスを返します。
ReactEventLoopLoop を使用する;ReactEventLoopLoopInterface を使用する;$loop = Loop::get();assert(LoopInterface の $loop インスタンス);assert($loop === Loop::get());
これは、オブジェクト指向プログラミング (OOP) と依存関係注入 (DI) を使用している場合に特に便利です。この場合、次のようにイベント ループ インスタンスを挿入し、 LoopInterface
でインスタンス メソッドを呼び出すことができます。
ReactEventLoopLoop を使用する;ReactEventLoopLoopInterface を使用する;クラス Greeter {プライベート $ループ;パブリック関数 __construct(LoopInterface $loop) {$this->loop = $loop; }パブリック関数greet(string $name) {$this->loop->addTimer(1.0, function () use ($name) {echo 'Hello ' . $name . '!' . PHP_EOL; }); } }$greeter = new Greeter(Loop::get());$greeter->greet('Alice');$greeter->greet('Bob');
使用可能なメソッドの詳細については、 LoopInterface
参照してください。
LoopInterface
に加えて、多数のイベント ループ実装が提供されています。
すべてのイベント ループは次の機能をサポートしています。
ファイル記述子のポーリング
ワンオフタイマー
定期タイマー
今後のループ ティックでの遅延実行
このパッケージのほとんどの利用者にとって、基礎となるイベント ループの実装は実装の詳細です。新しいインスタンスを自動的に作成するには、 Loop
クラスを使用する必要があります。
高度な!特定のイベント ループの実装が明示的に必要な場合は、次のいずれかのクラスを手動でインスタンス化できます。それぞれのイベント ループ実装に必要な PHP 拡張機能を最初にインストールする必要がある場合があります。そうしないと、作成時にBadMethodCallException
がスローされることに注意してください。
stream_select()
ベースのイベント ループ。
これはstream_select()
関数を使用しており、追加設定なしで PHP で動作する唯一の実装です。
このイベント ループは、どの PHP バージョンでもすぐに使用できます。つまり、インストールは必要なく、このライブラリはすべてのプラットフォームとサポートされている PHP バージョンで動作します。したがって、以下にリストされているイベント ループ拡張機能をインストールしない場合、 Loop
クラスはデフォルトでこのイベント ループを使用します。
内部では、単純なselect
システム コールを実行します。このシステム コールは、 FD_SETSIZE
の最大ファイル記述子数 (プラットフォームに依存し、通常は 1024) に制限され、 O(m)
で拡張されます ( m
渡される最大ファイル記述子数です)。これは、数千のストリームを同時に処理するときに問題が発生する可能性があることを意味しており、この場合は、以下にリストされている代替イベント ループ実装のいずれかの使用を検討する必要があるかもしれません。使用例が、一度に数十または数百のストリームのみを処理する一般的な使用例の 1 つである場合、このイベント ループの実装は非常に優れたパフォーマンスを発揮します。
シグナル処理 (以下のaddSignal()
も参照) を使用する場合、このイベント ループの実装にはext-pcntl
が必要です。この拡張機能は Unix 系プラットフォームでのみ利用可能であり、Windows はサポートしていません。通常、多くの PHP ディストリビューションの一部としてインストールされます。この拡張機能が存在しない場合 (または Windows で実行している場合)、シグナル処理はサポートされず、代わりにBadMethodCallException
がスローされます。
このイベント ループは、PHP 7.3 より前のバージョンを使用する場合、将来のタイマーをスケジュールするために実時間に依存することが知られています。これは、単調タイム ソースが PHP 7.3 ( hrtime()
) ) 以降でのみ使用できるためです。これは多くの一般的な使用例には影響しませんが、高い時間精度に依存するプログラムや、不連続な時間調整 (タイム ジャンプ) が発生するシステムにとっては重要な違いです。これは、PHP 7.3 未満で 30 秒でトリガーするようにタイマーをスケジュールし、その後システム時間を 20 秒進めて調整すると、タイマーが 10 秒でトリガーされる可能性があることを意味します。詳細については、 addTimer()
も参照してください。
ext-event
ベースのイベントループ。
これは、 libevent
ライブラリへのインターフェイスを提供するevent
PECL 拡張機能を使用します。 libevent
自体は、多数のシステム固有のバックエンド (epoll、kqueue) をサポートしています。
このループは、PHP 7.1 から PHP 8+ で動作することが知られています。
ext-ev
ベースのイベント ループ。
このループは、 libev
ライブラリへのインターフェイスを提供するev
PECL 拡張機能を使用します。 libev
自体は、多数のシステム固有のバックエンド (epoll、kqueue) をサポートしています。
このループは、PHP 7.1 から PHP 8+ で動作することが知られています。
ext-uv
ベースのイベント ループ。
このループは、 libuv
ライブラリへのインターフェイスを提供するuv
PECL 拡張機能を使用します。 libuv
自体は、多数のシステム固有のバックエンド (epoll、kqueue) をサポートしています。
このループは、PHP 7.1 から PHP 8+ で動作することが知られています。
run(): void
メソッドを使用すると、実行するタスクがなくなるまでイベント ループを実行できます。
多くのアプリケーションでは、このメソッドがイベント ループ上で直接表示される唯一の呼び出しです。経験則として、通常は、すべてを同じループ インスタンスにアタッチし、アプリケーションの下端でループを 1 回実行することをお勧めします。
$loop->run();
このメソッドは、実行するタスクがなくなるまでループを実行し続けます。言い換えると、このメソッドは、最後のタイマー、ストリーム、信号が削除されるまでブロックされます。
同様に、アプリケーションが実際にこのメソッドを 1 回呼び出すことを確認することが不可欠です。ループにリスナーを追加し、実際に実行しないと、アプリケーションは接続されたリスナーを実際に待たずに終了します。
ループがすでに実行されている間は、このメソッドを呼び出してはなりません。このメソッドは、明示的にstop()
が実行された後、または以前に何もすることがなくなったため自動的に停止した後、複数回呼び出すことができます。
stop(): void
メソッドを使用して、実行中のイベント ループの停止を指示できます。
この方法は高度な使用法であるため、注意して使用する必要があります。経験則として、通常はループを何もする必要がなくなった場合にのみ自動的に停止させることをお勧めします。
このメソッドを使用すると、イベント ループの停止を明示的に指示できます。
$loop->addTimer(3.0, function () use ($loop) {$loop->stop(); });
現在実行されていないループ インスタンス、またはすでに停止しているループ インスタンスに対してこのメソッドを呼び出しても、効果はありません。
addTimer(float $interval, callable $callback): TimerInterface
メソッドを使用して、指定された間隔の後に 1 回呼び出されるコールバックをキューに入れることができます。
2 番目のパラメータは、タイマー インスタンスを唯一のパラメータとして受け入れるタイマー コールバック関数でなければなりません。タイマー コールバック関数内でタイマー インスタンスを使用しない場合は、パラメーターをまったく持たない関数を使用しても構いません。
タイマー コールバック関数はException
をスローしてはなりません (MUST NOT)。タイマー コールバック関数の戻り値は無視され、何の効果もありません。そのため、パフォーマンス上の理由から、過剰なデータ構造を返さないことをお勧めします。
このメソッドはタイマー インスタンスを返します。前述のように、同じタイマー インスタンスがタイマー コールバック関数にも渡されます。 cancelTimer
呼び出して、保留中のタイマーをキャンセルできます。 addPeriodicTimer()
とは異なり、このメソッドは、指定された間隔の後にコールバックが 1 回だけ呼び出されるようにします。
$loop->addTimer(0.8, function () {echo 'world!' . PHP_EOL; });$loop->addTimer(0.3, function () {echo 'hello '; });
例 #1 も参照してください。
コールバック関数内の変数にアクセスしたい場合は、次のように任意のデータをコールバック クロージャにバインドできます。
関数 hello($name, LoopInterface $loop) {$loop->addTimer(1.0, function () use ($name) {echo "hello $namen"; }); }hello('テスター', $loop);
このインターフェイスは特定のタイマー解像度を強制しないため、ミリ秒以下の非常に高い精度に依存する場合は特別な注意が必要になる場合があります。イベント ループの実装は、特に明記されていない限り、ベスト エフォート ベースで動作する必要があり、少なくともミリ秒の精度を提供する必要があります。既存のイベント ループ実装の多くはマイクロ秒の精度を提供することが知られていますが、この高精度に依存することは一般的に推奨されません。
同様に、同時に実行するようにスケジュールされたタイマーの実行順序 (可能な精度の範囲内) は保証されません。
このインターフェースは、イベント ループの実装では、利用可能な場合は単調タイム ソースを使用する必要がある (SHOULD) ことを示唆しています。単調タイムソースがデフォルトで PHP 7.3 以降でのみ利用可能であることを考慮すると、イベントループ実装は実時間の使用にフォールバックしてもよい(MAY)。これは多くの一般的な使用例には影響しませんが、高い時間精度に依存するプログラムや、不連続な時間調整 (タイム ジャンプ) が発生するシステムにとっては重要な違いです。これは、タイマーを 30 秒でトリガーするようにスケジュールし、システム時間を 20 秒進めて調整した場合でも、タイマーは 30 秒でトリガーする必要があることを意味します。詳細については、イベント ループの実装も参照してください。
addPeriodicTimer(float $interval, callable $callback): TimerInterface
メソッドを使用して、指定された間隔の後に繰り返し呼び出されるコールバックをキューに入れることができます。
2 番目のパラメータは、タイマー インスタンスを唯一のパラメータとして受け入れるタイマー コールバック関数でなければなりません。タイマー コールバック関数内でタイマー インスタンスを使用しない場合は、パラメーターをまったく持たない関数を使用しても構いません。
タイマー コールバック関数はException
をスローしてはなりません (MUST NOT)。タイマー コールバック関数の戻り値は無視され、何の効果もありません。そのため、パフォーマンス上の理由から、過剰なデータ構造を返さないことをお勧めします。
このメソッドはタイマー インスタンスを返します。前述のように、同じタイマー インスタンスがタイマー コールバック関数にも渡されます。 addTimer()
とは異なり、このメソッドは、指定された間隔の後、またはcancelTimer
呼び出すまで、コールバックが無限に呼び出されることを保証します。
$timer = $loop->addPeriodicTimer(0.1, function () {echo 'tick!' . PHP_EOL; });$loop->addTimer(1.0, function () use ($loop, $timer) {$loop->cancelTimer($timer);echo 'Done' . PHP_EOL; });
例 #2 も参照してください。
実行数を制限したい場合は、次のように任意のデータをコールバック クロージャにバインドできます。
関数 hello($name, LoopInterface $loop) {$n = 3;$loop->addPeriodicTimer(1.0, 関数 ($timer) use ($name, $loop, &$n) {if ($n > 0) { --$n;エコー "こんにちは $namen"; else {$loop->cancelTimer($timer); } }); }hello('テスター', $loop);
このインターフェイスは特定のタイマー解像度を強制しないため、ミリ秒以下の非常に高い精度に依存する場合は特別な注意が必要になる場合があります。イベント ループの実装は、特に明記されていない限り、ベスト エフォート ベースで動作する必要があり、少なくともミリ秒の精度を提供する必要があります。既存のイベント ループ実装の多くはマイクロ秒の精度を提供することが知られていますが、この高精度に依存することは一般的に推奨されません。
同様に、同時に実行するようにスケジュールされたタイマーの実行順序 (可能な精度の範囲内) は保証されません。
このインターフェースは、イベント ループの実装では、利用可能な場合は単調タイム ソースを使用する必要がある (SHOULD) ことを示唆しています。単調タイムソースがデフォルトで PHP 7.3 以降でのみ利用可能であることを考慮すると、イベントループ実装は実時間の使用にフォールバックしてもよい(MAY)。これは多くの一般的な使用例には影響しませんが、高い時間精度に依存するプログラムや、不連続な時間調整 (タイム ジャンプ) が発生するシステムにとっては重要な違いです。これは、タイマーを 30 秒でトリガーするようにスケジュールし、システム時間を 20 秒進めて調整した場合でも、タイマーは 30 秒でトリガーする必要があることを意味します。詳細については、イベント ループの実装も参照してください。
さらに、定期タイマーは、各呼び出し後の再スケジュールによりタイマーのドリフトが発生する可能性があります。そのため、ミリ秒以下の精度の高精度間隔についてはこれに依存することは一般的に推奨されません。
cancelTimer(TimerInterface $timer): void
メソッドを使用して、保留中のタイマーをキャンセルできます。
addPeriodicTimer()
と例 2 も参照してください。
このループ インスタンスに追加されていないタイマー インスタンス、またはすでにキャンセルされているタイマーに対してこのメソッドを呼び出しても、効果はありません。
futureTick(callable $listener): void
メソッドを使用して、イベント ループの将来のティックで呼び出されるコールバックをスケジュールすることができます。
これは、間隔が 0 秒のタイマーと非常によく似ていますが、タイマー キューをスケジュールするオーバーヘッドは必要ありません。
ティック コールバック関数は、ゼロのパラメーターを受け入れることができなければなりません (MUST)。
ティック コールバック関数はException
をスローしてはなりません (MUST NOT)。ティック コールバック関数の戻り値は無視され、何の効果もありません。そのため、パフォーマンス上の理由から、過剰なデータ構造を返さないことをお勧めします。
コールバック関数内の変数にアクセスしたい場合は、次のように任意のデータをコールバック クロージャにバインドできます。
関数 hello($name, LoopInterface $loop) {$loop->futureTick(function () use ($name) {echo "hello $namen"; }); }hello('テスター', $loop);
タイマーとは異なり、ティック コールバックはキューに入れられた順序で実行されることが保証されています。また、コールバックがキューに入れられると、この操作をキャンセルする方法はありません。
これは、大きなタスクを小さなステップに分割するためによく使用されます (協調的なマルチタスクの一種)。
$loop->futureTick(function() {echo 'b'; });$loop->futureTick(function () {echo 'c'; });エコー 'a';
例 3 も参照してください。
addSignal(int $signal, callable $listener): void
メソッドを使用して、このプロセスによってシグナルがキャッチされたときに通知を受けるリスナーを登録できます。
これは、ユーザーの割り込み信号や、 supervisor
やsystemd
などのツールからのシャットダウン信号をキャッチするのに役立ちます。
2 番目のパラメータは、シグナルを唯一のパラメータとして受け入れるリスナー コールバック関数でなければなりません。リスナー コールバック関数内でシグナルを使用しない場合は、パラメーターをまったく持たない関数を使用しても構いません。
リスナー コールバック関数はException
をスローしてはなりません (MUST NOT)。リスナー コールバック関数の戻り値は無視され、何の効果もありません。そのため、パフォーマンス上の理由から、過剰なデータ構造を返さないことをお勧めします。
$loop->addSignal(SIGINT, function (int $signal) {echo 'ユーザー割り込み信号を捕捉' . PHP_EOL; });
例 4 も参照してください。
シグナリングは Unix のようなプラットフォームでのみ使用でき、Windows はオペレーティング システムの制限によりサポートされません。このプラットフォームでシグナルがサポートされていない場合、たとえば必要な拡張機能が欠落している場合、このメソッドはBadMethodCallException
をスローすることがあります。
注: リスナーは同じシグナルに 1 回のみ追加でき、複数回追加しようとしても無視されます。
removeSignal(int $signal, callable $listener): void
メソッドを使用して、以前に追加したシグナル リスナーを削除できます。
$loop->removeSignal(SIGINT, $listener);
登録されていないリスナーを削除しようとしても無視されます。
高度な!この低レベル API は高度な使用法とみなされることに注意してください。ほとんどのユースケースでは、おそらく、代わりに高レベルの読み取り可能な Stream API を使用する必要があります。
addReadStream(resource $stream, callable $callback): void
メソッドを使用して、ストリームの読み取り準備ができたときに通知を受けるリスナーを登録できます。
最初のパラメータは、このループ実装による読み取りの準備ができているかどうかのチェックをサポートする有効なストリーム リソースでなければなりません。単一のストリーム リソースを複数回追加してはなりません。代わりに、最初にremoveReadStream()
呼び出すか、単一のリスナーでこのイベントに反応してからこのリスナーからディスパッチしてください。指定されたリソースタイプがこのループ実装でサポートされていない場合、このメソッドはException
をスローしてもよい(MAY)。
2 番目のパラメータは、ストリーム リソースを唯一のパラメータとして受け入れるリスナー コールバック関数でなければなりません。リスナー コールバック関数内でストリーム リソースを使用しない場合は、パラメータをまったく持たない関数を使用してもよいです。
リスナー コールバック関数はException
をスローしてはなりません (MUST NOT)。リスナー コールバック関数の戻り値は無視され、何の効果もありません。そのため、パフォーマンス上の理由から、過剰なデータ構造を返さないことをお勧めします。
コールバック関数内の変数にアクセスしたい場合は、次のように任意のデータをコールバック クロージャにバインドできます。
$loop->addReadStream($stream, function ($stream) use ($name) {echo $name . ' 言いました: ' . fread($stream); });
例 #11 も参照してください。
removeReadStream()
呼び出して、このストリームの読み取りイベント リスナーを削除できます。
複数のストリームが同時に準備可能になった場合のリスナーの実行順序は保証されません。
一部のイベント ループ実装は、ストリームが読み取り可能になった場合 (エッジ トリガー) にのみリスナーをトリガーし、ストリームが最初からすでに読み取り可能になっている場合はトリガーしないことが知られています。これは、データが PHP の内部ストリーム バッファーに残っている場合、ストリームが読み取り可能として認識されない可能性があることも意味します。したがって、 stream_set_read_buffer($stream, 0);
この場合、PHP の内部読み取りバッファを無効にします。
高度な!この低レベル API は高度な使用法とみなされることに注意してください。ほとんどのユースケースでは、おそらく、代わりに高レベルの書き込み可能な Stream API を使用する必要があります。
addWriteStream(resource $stream, callable $callback): void
メソッドを使用して、ストリームの書き込み準備ができたときに通知を受けるリスナーを登録できます。
最初のパラメータは、このループ実装による書き込みの準備ができているかどうかのチェックをサポートする有効なストリーム リソースでなければなりません。単一のストリーム リソースを複数回追加してはなりません。代わりに、最初にremoveWriteStream()
呼び出すか、単一のリスナーでこのイベントに反応してからこのリスナーからディスパッチしてください。指定されたリソースタイプがこのループ実装でサポートされていない場合、このメソッドはException
をスローしてもよい(MAY)。
2 番目のパラメータは、ストリーム リソースを唯一のパラメータとして受け入れるリスナー コールバック関数でなければなりません。リスナー コールバック関数内でストリーム リソースを使用しない場合は、パラメータをまったく持たない関数を使用してもよいです。
リスナー コールバック関数はException
をスローしてはなりません (MUST NOT)。リスナー コールバック関数の戻り値は無視され、何の効果もありません。そのため、パフォーマンス上の理由から、過剰なデータ構造を返さないことをお勧めします。
コールバック関数内の変数にアクセスしたい場合は、次のように任意のデータをコールバック クロージャにバインドできます。
$loop->addWriteStream($stream, function ($stream) use ($name) {fwrite($stream, 'Hello ' . $name); });
例 #12 も参照してください。
removeWriteStream()
呼び出して、このストリームの書き込みイベント リスナーを削除できます。
複数のストリームが同時に準備可能になった場合のリスナーの実行順序は保証されません。
removeReadStream(resource $stream): void
メソッドを使用すると、指定されたストリームの読み取りイベント リスナーを削除できます。
すでに削除されているループからストリームを削除したり、追加されていないストリームや無効なストリームを削除しようとしても効果はありません。
removeWriteStream(resource $stream): void
メソッドを使用すると、指定されたストリームの書き込みイベント リスナーを削除できます。
すでに削除されているループからストリームを削除したり、追加されていないストリームや無効なストリームを削除しようとしても効果はありません。
このライブラリをインストールする推奨方法は、Composer を使用することです。作曲家は初めてですか?
このプロジェクトがリリースされると、SemVer に続くことになります。現時点では、これにより最新の開発バージョンがインストールされます。
コンポーザーには反応/イベントループが必要です:^3@dev
バージョンアップの詳細については、CHANGELOG も参照してください。
このプロジェクトはあらゆるプラットフォームで実行することを目的としているため、PHP 拡張機能は必要なく、PHP 7.1 から現在の PHP 8+ での実行をサポートします。このプロジェクトでは、サポートされている最新の PHP バージョンを使用することを強くお勧めします。
イベント ループ拡張機能のいずれかをインストールすることをお勧めしますが、完全にオプションです。詳細については、イベント ループの実装も参照してください。
テスト スイートを実行するには、まずこのリポジトリのクローンを作成し、次に Composer を通じてすべての依存関係をインストールする必要があります。
コンポーザーのインストール
テスト スイートを実行するには、プロジェクト ルートに移動して次を実行します。
ベンダー/bin/phpunit
MIT の場合は、LICENSE ファイルを参照してください。
実際のアプリケーションでストリームがどのように使用されるかについて詳しくは、「ストリーム コンポーネント」を参照してください。
実際のアプリケーションで EventLoop を使用するパッケージのリストについては、ユーザーの Wiki と Packagist の依存パッケージを参照してください。