diff --git a/README.md b/README.md index aa80be6e..3aa0cc45 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ For the code of the current stable 0.4.x release, checkout the * [Install](#install) * [Tests](#tests) * [License](#license) +* [More](#more) ## Quickstart example @@ -291,6 +292,116 @@ echo 'a'; See also [example #3](examples). +### addReadStream() + +> Advanced! Note that this low-level API is considered advanced usage. + Most use cases should probably use the higher-level + [readable Stream API](https://github.com/reactphp/stream#readablestreaminterface) + instead. + +The `addReadStream(resource $stream, callable $callback): void` method can be used to +register a listener to be notified when a stream is ready to read. + +The first parameter MUST be a valid stream resource that supports +checking whether it is ready to read by this loop implementation. +A single stream resource MUST NOT be added more than once. +Instead, either call [`removeReadStream()`](#removereadstream) first or +react to this event with a single listener and then dispatch from this +listener. + +The listener callback function MUST be able to accept a single parameter, +the stream resource added by this method or you MAY use a function which +has no parameters at all. + +The listener callback function MUST NOT throw an `Exception`. +The return value of the listener callback function will be ignored and has +no effect, so for performance reasons you're recommended to not return +any excessive data structures. + +If you want to access any variables within your callback function, you +can bind arbitrary data to a callback closure like this: + +```php +$loop->addReadStream($stream, function ($stream) use ($name) { + echo $name . ' said: ' . fread($stream); +}); +``` + +See also [example #11](examples). + +You can invoke [`removeReadStream()`](#removereadstream) to remove the +read event listener for this stream. + +The execution order of listeners when multiple streams become ready at +the same time is not guaranteed. + +### addWriteStream() + +> Advanced! Note that this low-level API is considered advanced usage. + Most use cases should probably use the higher-level + [writable Stream API](https://github.com/reactphp/stream#writablestreaminterface) + instead. + +The `addWriteStream(resource $stream, callable $callback): void` method can be used to +register a listener to be notified when a stream is ready to write. + +The first parameter MUST be a valid stream resource that supports +checking whether it is ready to write by this loop implementation. +A single stream resource MUST NOT be added more than once. +Instead, either call [`removeWriteStream()`](#removewritestream) first or +react to this event with a single listener and then dispatch from this +listener. + +The listener callback function MUST be able to accept a single parameter, +the stream resource added by this method or you MAY use a function which +has no parameters at all. + +The listener callback function MUST NOT throw an `Exception`. +The return value of the listener callback function will be ignored and has +no effect, so for performance reasons you're recommended to not return +any excessive data structures. + +If you want to access any variables within your callback function, you +can bind arbitrary data to a callback closure like this: + +```php +$loop->addWriteStream($stream, function ($stream) use ($name) { + fwrite($stream, 'Hello ' . $name); +}); +``` + +See also [example #12](examples). + +You can invoke [`removeWriteStream()`](#removewritestream) to remove the +write event listener for this stream. + +The execution order of listeners when multiple streams become ready at +the same time is not guaranteed. + +### removeReadStream() + +The `removeReadStream(resource $stream): void` method can be used to +remove the read event listener for the given stream. + +Removing a stream from the loop that has already been removed or trying +to remove a stream that was never added or is invalid has no effect. + +### removeWriteStream() + +The `removeWriteStream(resource $stream): void` method can be used to +remove the write event listener for the given stream. + +Removing a stream from the loop that has already been removed or trying +to remove a stream that was never added or is invalid has no effect. + +### removeStream() + +The `removeStream(resource $stream): void` method can be used to +remove all listeners for the given stream. + +Removing a stream from the loop that has already been removed or trying +to remove a stream that was never added or is invalid has no effect. + ## Install The recommended way to install this library is [through Composer](http://getcomposer.org). @@ -320,3 +431,11 @@ $ php vendor/bin/phpunit ## License MIT, see [LICENSE file](LICENSE). + +## More + +* See our [Stream component](https://github.com/reactphp/stream) for more + information on how streams are used in real-world applications. +* See our [users wiki](https://github.com/reactphp/react/wiki/Users) and the + [dependents on Packagist](https://packagist.org/packages/react/event-loop/dependents) + for a list of packages that use the EventLoop in real-world applications. diff --git a/src/ExtEventLoop.php b/src/ExtEventLoop.php index e50b8777..0d088d50 100644 --- a/src/ExtEventLoop.php +++ b/src/ExtEventLoop.php @@ -289,11 +289,11 @@ private function createStreamCallback() $key = (int) $stream; if (Event::READ === (Event::READ & $flags) && isset($this->readListeners[$key])) { - call_user_func($this->readListeners[$key], $stream, $this); + call_user_func($this->readListeners[$key], $stream); } if (Event::WRITE === (Event::WRITE & $flags) && isset($this->writeListeners[$key])) { - call_user_func($this->writeListeners[$key], $stream, $this); + call_user_func($this->writeListeners[$key], $stream); } }; } diff --git a/src/LibEvLoop.php b/src/LibEvLoop.php index f6f0f490..3bbd8c4e 100644 --- a/src/LibEvLoop.php +++ b/src/LibEvLoop.php @@ -40,7 +40,7 @@ public function addReadStream($stream, callable $listener) } $callback = function () use ($stream, $listener) { - call_user_func($listener, $stream, $this); + call_user_func($listener, $stream); }; $event = new IOEvent($callback, $stream, IOEvent::READ); @@ -59,7 +59,7 @@ public function addWriteStream($stream, callable $listener) } $callback = function () use ($stream, $listener) { - call_user_func($listener, $stream, $this); + call_user_func($listener, $stream); }; $event = new IOEvent($callback, $stream, IOEvent::WRITE); diff --git a/src/LibEventLoop.php b/src/LibEventLoop.php index 4b252d45..ee648e7f 100644 --- a/src/LibEventLoop.php +++ b/src/LibEventLoop.php @@ -307,11 +307,11 @@ private function createStreamCallback() $key = (int) $stream; if (EV_READ === (EV_READ & $flags) && isset($this->readListeners[$key])) { - call_user_func($this->readListeners[$key], $stream, $this); + call_user_func($this->readListeners[$key], $stream); } if (EV_WRITE === (EV_WRITE & $flags) && isset($this->writeListeners[$key])) { - call_user_func($this->writeListeners[$key], $stream, $this); + call_user_func($this->writeListeners[$key], $stream); } }; } diff --git a/src/LoopInterface.php b/src/LoopInterface.php index 789ef192..a4d394c0 100644 --- a/src/LoopInterface.php +++ b/src/LoopInterface.php @@ -7,24 +7,105 @@ interface LoopInterface { /** - * Register a listener to be notified when a stream is ready to read. + * [Advanced] Register a listener to be notified when a stream is ready to read. + * + * Note that this low-level API is considered advanced usage. + * Most use cases should probably use the higher-level + * [readable Stream API](https://github.com/reactphp/stream#readablestreaminterface) + * instead. + * + * The first parameter MUST be a valid stream resource that supports + * checking whether it is ready to read by this loop implementation. + * A single stream resource MUST NOT be added more than once. + * Instead, either call [`removeReadStream()`](#removereadstream) first or + * react to this event with a single listener and then dispatch from this + * listener. + * + * The listener callback function MUST be able to accept a single parameter, + * the stream resource added by this method or you MAY use a function which + * has no parameters at all. + * + * The listener callback function MUST NOT throw an `Exception`. + * The return value of the listener callback function will be ignored and has + * no effect, so for performance reasons you're recommended to not return + * any excessive data structures. + * + * If you want to access any variables within your callback function, you + * can bind arbitrary data to a callback closure like this: + * + * ```php + * $loop->addReadStream($stream, function ($stream) use ($name) { + * echo $name . ' said: ' . fread($stream); + * }); + * ``` + * + * See also [example #11](examples). + * + * You can invoke [`removeReadStream()`](#removereadstream) to remove the + * read event listener for this stream. + * + * The execution order of listeners when multiple streams become ready at + * the same time is not guaranteed. * * @param resource $stream The PHP stream resource to check. * @param callable $listener Invoked when the stream is ready. + * @see self::removeReadStream() */ public function addReadStream($stream, callable $listener); /** - * Register a listener to be notified when a stream is ready to write. + * [Advanced] Register a listener to be notified when a stream is ready to write. + * + * Note that this low-level API is considered advanced usage. + * Most use cases should probably use the higher-level + * [writable Stream API](https://github.com/reactphp/stream#writablestreaminterface) + * instead. + * + * The first parameter MUST be a valid stream resource that supports + * checking whether it is ready to write by this loop implementation. + * A single stream resource MUST NOT be added more than once. + * Instead, either call [`removeWriteStream()`](#removewritestream) first or + * react to this event with a single listener and then dispatch from this + * listener. + * + * The listener callback function MUST be able to accept a single parameter, + * the stream resource added by this method or you MAY use a function which + * has no parameters at all. + * + * The listener callback function MUST NOT throw an `Exception`. + * The return value of the listener callback function will be ignored and has + * no effect, so for performance reasons you're recommended to not return + * any excessive data structures. + * + * If you want to access any variables within your callback function, you + * can bind arbitrary data to a callback closure like this: + * + * ```php + * $loop->addWriteStream($stream, function ($stream) use ($name) { + * fwrite($stream, 'Hello ' . $name); + * }); + * ``` + * + * See also [example #12](examples). + * + * You can invoke [`removeWriteStream()`](#removewritestream) to remove the + * write event listener for this stream. + * + * The execution order of listeners when multiple streams become ready at + * the same time is not guaranteed. * * @param resource $stream The PHP stream resource to check. * @param callable $listener Invoked when the stream is ready. + * @see self::removeWriteStream() */ public function addWriteStream($stream, callable $listener); /** * Remove the read event listener for the given stream. * + * Removing a stream from the loop that has already been removed or trying + * to remove a stream that was never added or is invalid has no effect. + * * @param resource $stream The PHP stream resource. */ public function removeReadStream($stream); @@ -32,6 +113,9 @@ public function removeReadStream($stream); /** * Remove the write event listener for the given stream. * + * Removing a stream from the loop that has already been removed or trying + * to remove a stream that was never added or is invalid has no effect. + * * @param resource $stream The PHP stream resource. */ public function removeWriteStream($stream); @@ -39,6 +123,9 @@ public function removeWriteStream($stream); /** * Remove all listeners for the given stream. * + * Removing a stream from the loop that has already been removed or trying + * to remove a stream that was never added or is invalid has no effect. + * * @param resource $stream The PHP stream resource. */ public function removeStream($stream); diff --git a/src/StreamSelectLoop.php b/src/StreamSelectLoop.php index 053948aa..085c7703 100644 --- a/src/StreamSelectLoop.php +++ b/src/StreamSelectLoop.php @@ -206,7 +206,7 @@ private function waitForStreamActivity($timeout) $key = (int) $stream; if (isset($this->readListeners[$key])) { - call_user_func($this->readListeners[$key], $stream, $this); + call_user_func($this->readListeners[$key], $stream); } } @@ -214,7 +214,7 @@ private function waitForStreamActivity($timeout) $key = (int) $stream; if (isset($this->writeListeners[$key])) { - call_user_func($this->writeListeners[$key], $stream, $this); + call_user_func($this->writeListeners[$key], $stream); } } } diff --git a/tests/StreamSelectLoopTest.php b/tests/StreamSelectLoopTest.php index d2e3e078..247070e2 100644 --- a/tests/StreamSelectLoopTest.php +++ b/tests/StreamSelectLoopTest.php @@ -90,11 +90,11 @@ public function testSignalInterruptWithStream($signal) // add stream to the loop list($writeStream, $readStream) = $this->createSocketPair(); - $this->loop->addReadStream($readStream, function($stream, $loop) { + $this->loop->addReadStream($readStream, function ($stream) { /** @var $loop LoopInterface */ $read = fgets($stream); if ($read === "end loop\n") { - $loop->stop(); + $this->loop->stop(); } }); $this->loop->addTimer(0.05, function() use ($writeStream) {