Skip to content

Commit

Permalink
Merge pull request #110 from clue-labs/streams
Browse files Browse the repository at this point in the history
Documentation for advanced stream API
  • Loading branch information
WyriHaximus authored Oct 14, 2017
2 parents ddee079 + 8047bce commit 6090eb7
Show file tree
Hide file tree
Showing 7 changed files with 218 additions and 12 deletions.
119 changes: 119 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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).
Expand Down Expand Up @@ -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.
4 changes: 2 additions & 2 deletions src/ExtEventLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
};
}
Expand Down
4 changes: 2 additions & 2 deletions src/LibEvLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions src/LibEventLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
};
}
Expand Down
91 changes: 89 additions & 2 deletions src/LoopInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,125 @@
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);

/**
* 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);

/**
* 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);
Expand Down
4 changes: 2 additions & 2 deletions src/StreamSelectLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -206,15 +206,15 @@ 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);
}
}

foreach ($write as $stream) {
$key = (int) $stream;

if (isset($this->writeListeners[$key])) {
call_user_func($this->writeListeners[$key], $stream, $this);
call_user_func($this->writeListeners[$key], $stream);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/StreamSelectLoopTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,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.1, function() use ($writeStream) {
Expand Down

0 comments on commit 6090eb7

Please sign in to comment.