From 9a6c2b9c9afa1f8d89b83ba753b2f51ffba5f9dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Fri, 1 Dec 2017 15:56:38 +0100 Subject: [PATCH 1/3] Add all sections to TOC --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index d98e4c73..870a2a63 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,19 @@ For the code of the current stable 0.4.x release, checkout the * [Quickstart example](#quickstart-example) * [Usage](#usage) +* [Factory](#factory) * [Loop implementations](#loop-implementations) + * [addtimer()](#addtimer) + * [addPeriodicTimer()](#addperiodictimer) + * [cancelTimer()](#canceltimer) + * [isTimerActive()](#istimeractive) + * [futureTick()](#futuretick) + * [addSignal()](#addsignal) + * [removeSignal()](#removesignal) + * [addReadStream()](#addreadstream) + * [addWriteStream()](#addwritestream) + * [removeReadStream()](#removereadstream) + * [removeWriteStream()](#removewritestream) * [Install](#install) * [Tests](#tests) * [License](#license) From 5944b2daff8e96e6b9d64581b17589b8ba5a5a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Sat, 2 Dec 2017 16:13:07 +0100 Subject: [PATCH 2/3] Documentation for event loop implementations --- README.md | 136 ++++++++++++++++++++++++++------------- src/ExtEventLoop.php | 7 +- src/Factory.php | 6 +- src/LibEvLoop.php | 5 ++ src/LibEventLoop.php | 7 +- src/StreamSelectLoop.php | 9 ++- 6 files changed, 118 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 870a2a63..37e6de74 100644 --- a/README.md +++ b/README.md @@ -18,19 +18,25 @@ For the code of the current stable 0.4.x release, checkout the * [Quickstart example](#quickstart-example) * [Usage](#usage) -* [Factory](#factory) -* [Loop implementations](#loop-implementations) - * [addtimer()](#addtimer) - * [addPeriodicTimer()](#addperiodictimer) - * [cancelTimer()](#canceltimer) - * [isTimerActive()](#istimeractive) - * [futureTick()](#futuretick) - * [addSignal()](#addsignal) - * [removeSignal()](#removesignal) - * [addReadStream()](#addreadstream) - * [addWriteStream()](#addwritestream) - * [removeReadStream()](#removereadstream) - * [removeWriteStream()](#removewritestream) + * [Factory](#factory) + * [create()](#create) + * [Loop implementations](#loop-implementations) + * [StreamSelectLoop](#streamselectloop) + * [LibEventLoop](#libeventloop) + * [LibEvLoop](#libevloop) + * [ExtEventLoop](#exteventloop) + * [LoopInterface](#loopinterface) + * [addtimer()](#addtimer) + * [addPeriodicTimer()](#addperiodictimer) + * [cancelTimer()](#canceltimer) + * [isTimerActive()](#istimeractive) + * [futureTick()](#futuretick) + * [addSignal()](#addsignal) + * [removeSignal()](#removesignal) + * [addReadStream()](#addreadstream) + * [addWriteStream()](#addwritestream) + * [removeReadStream()](#removereadstream) + * [removeWriteStream()](#removewritestream) * [Install](#install) * [Tests](#tests) * [License](#license) @@ -106,49 +112,79 @@ $loop->run(); purposes. 3. The loop is run with a single `$loop->run()` call at the end of the program. -## Factory +### Factory The `Factory` class exists as a convenient way to pick the best available -[loop implementation](#loop-implementations). +[event loop implementation](#loop-implementations). -The `create(): LoopInterface` method can be used to create a new loop +#### create() + +The `create(): LoopInterface` method can be used to create a new event loop instance: ```php $loop = React\EventLoop\Factory::create(); ``` -This method always returns an instance implementing `LoopInterface`, -the actual loop implementation is an implementation detail. +This method always returns an instance implementing [`LoopInterface`](#loopinterface), +the actual [event loop implementation](#loop-implementations) is an implementation detail. This method should usually only be called once at the beginning of the program. -## Loop implementations - -In addition to the interface there are the following implementations provided: - -* `StreamSelectLoop`: This is the only implementation which works out of the - box with PHP. It does a simple `select` system call. It's not the most - performant of loops, but still does the job quite well. +### Loop implementations -* `LibEventLoop`: This uses the `libevent` pecl extension. `libevent` itself - supports a number of system-specific backends (epoll, kqueue). +In addition to the [`LoopInterface`](#loopinterface), there are a number of +event loop implementations provided. -* `LibEvLoop`: This uses the `libev` pecl extension - ([github](https://github.com/m4rw3r/php-libev)). It supports the same - backends as libevent. - -* `ExtEventLoop`: This uses the `event` pecl extension. It supports the same - backends as libevent. - -All of the loops support these features: +All of the event loops support these features: * File descriptor polling * One-off timers * Periodic timers * Deferred execution on future loop tick -### addTimer() +For most consumers of this package, the underlying event loop implementation is +an implementation detail. +You should use the [`Factory`](#factory) to automatically create a new instance. + +Advanced! If you explicitly need a certain event loop implementation, you can +manually instantiate one of the following classes. +Note that you may have to install the required PHP extensions for the respective +event loop implementation first or this may result in a fatal error. + +#### StreamSelectLoop + +A `stream_select()` based event loop. + +This uses the [`stream_select()`](http://php.net/manual/en/function.stream-select.php) +function and is the only implementation which works out of the box with PHP. +It does a simple `select` system call. +It's not the most performant of loops, but still does the job quite well. + +#### LibEventLoop + +An `ext-libevent` based event loop. + +This uses the [`libevent` PECL extension](https://pecl.php.net/package/libevent). +`libevent` itself supports a number of system-specific backends (epoll, kqueue). + +#### LibEvLoop + +An `ext-libev` based event loop. + +This uses an [unofficial `libev` extension](https://github.com/m4rw3r/php-libev). +It supports the same backends as libevent. + +#### ExtEventLoop + +An `ext-event` based event loop. + +This uses the [`event` PECL extension](https://pecl.php.net/package/event). +It supports the same backends as libevent. + +### LoopInterface + +#### addTimer() The `addTimer(float $interval, callable $callback): TimerInterface` method can be used to enqueue a callback to be invoked once after the given interval. @@ -195,7 +231,7 @@ hello('Tester', $loop); The execution order of timers scheduled to execute at the same time is not guaranteed. -### addPeriodicTimer() +#### addPeriodicTimer() The `addPeriodicTimer(float $interval, callable $callback): TimerInterface` method can be used to enqueue a callback to be invoked repeatedly after the given interval. @@ -249,7 +285,7 @@ hello('Tester', $loop); The execution order of timers scheduled to execute at the same time is not guaranteed. -### cancelTimer() +#### cancelTimer() The `cancelTimer(TimerInterface $timer): void` method can be used to cancel a pending timer. @@ -264,7 +300,7 @@ Calling this method on a timer instance that has not been added to this loop instance or on a timer that is not "active" (or has already been cancelled) has no effect. -### isTimerActive() +#### isTimerActive() The `isTimerActive(TimerInterface $timer): bool` method can be used to check if a given timer is active. @@ -274,7 +310,7 @@ via [`addTimer()`](#addtimer) or [`addPeriodicTimer()`](#addperiodictimer) and has not been cancelled via [`cancelTimer()`](#canceltimer) and is not a non-periodic timer that has already been triggered after its interval. -### futureTick() +#### futureTick() The `futureTick(callable $listener): void` method can be used to schedule a callback to be invoked on a future tick of the event loop. @@ -322,7 +358,7 @@ echo 'a'; See also [example #3](examples). -### addSignal() +#### addSignal() The `addSignal(int $signal, callable $listener): void` method can be used to register a listener to be notified when a signal has been caught by this process. @@ -356,7 +392,7 @@ missing. **Note: A listener can only be added once to the same signal, any attempts to add it more then once will be ignored.** -### removeSignal() +#### removeSignal() The `removeSignal(int $signal, callable $listener): void` method can be used to remove a previously added signal listener. @@ -367,7 +403,7 @@ $loop->removeSignal(SIGINT, $listener); Any attempts to remove listeners that aren't registered will be ignored. -### addReadStream() +#### addReadStream() > Advanced! Note that this low-level API is considered advanced usage. Most use cases should probably use the higher-level @@ -410,7 +446,7 @@ read event listener for this stream. The execution order of listeners when multiple streams become ready at the same time is not guaranteed. -### addWriteStream() +#### addWriteStream() > Advanced! Note that this low-level API is considered advanced usage. Most use cases should probably use the higher-level @@ -453,7 +489,7 @@ write event listener for this stream. The execution order of listeners when multiple streams become ready at the same time is not guaranteed. -### removeReadStream() +#### removeReadStream() The `removeReadStream(resource $stream): void` method can be used to remove the read event listener for the given stream. @@ -461,7 +497,7 @@ 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() +#### removeWriteStream() The `removeWriteStream(resource $stream): void` method can be used to remove the write event listener for the given stream. @@ -480,6 +516,14 @@ This will install the latest supported version: $ composer require react/event-loop ``` +This project aims to run on any platform and thus does not require any PHP +extensions and supports running on legacy PHP 5.4 through current PHP 7+ and +HHVM. +It's *highly recommended to use PHP 7+* for this project. + +Installing any of the event loop extensions is suggested, but entirely optional. +See also [event loop implementations](#loop-implementations) for more details. + ## Tests To run the test suite, you first need to clone this repo and then install all diff --git a/src/ExtEventLoop.php b/src/ExtEventLoop.php index 05653c6e..eb08e9b3 100644 --- a/src/ExtEventLoop.php +++ b/src/ExtEventLoop.php @@ -11,7 +11,12 @@ use SplObjectStorage; /** - * An ext-event based event-loop. + * An `ext-event` based event loop. + * + * This uses the [`event` PECL extension](https://pecl.php.net/package/event). + * It supports the same backends as libevent. + * + * @link https://pecl.php.net/package/event */ class ExtEventLoop implements LoopInterface { diff --git a/src/Factory.php b/src/Factory.php index 7c87180c..0e868358 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -3,19 +3,19 @@ namespace React\EventLoop; /** - * The `Factory` class exists as a convenient way to pick the best available loop implementation. + * The `Factory` class exists as a convenient way to pick the best available event loop implementation. */ class Factory { /** - * Creates a new loop instance + * Creates a new event loop instance * * ```php * $loop = React\EventLoop\Factory::create(); * ``` * * This method always returns an instance implementing `LoopInterface`, - * the actual loop implementation is an implementation detail. + * the actual event loop implementation is an implementation detail. * * This method should usually only be called once at the beginning of the program. * diff --git a/src/LibEvLoop.php b/src/LibEvLoop.php index 47701118..5dbaf62a 100644 --- a/src/LibEvLoop.php +++ b/src/LibEvLoop.php @@ -12,6 +12,11 @@ use SplObjectStorage; /** + * An `ext-libev` based event loop. + * + * This uses an [unofficial `libev` extension](https://github.com/m4rw3r/php-libev). + * It supports the same backends as libevent. + * * @see https://github.com/m4rw3r/php-libev * @see https://gist.github.com/1688204 */ diff --git a/src/LibEventLoop.php b/src/LibEventLoop.php index 2e5a6c80..2a1ee6aa 100644 --- a/src/LibEventLoop.php +++ b/src/LibEventLoop.php @@ -10,7 +10,12 @@ use SplObjectStorage; /** - * An ext-libevent based event-loop. + * An `ext-libevent` based event loop. + * + * This uses the [`libevent` PECL extension](https://pecl.php.net/package/libevent). + * `libevent` itself supports a number of system-specific backends (epoll, kqueue). + * + * @link https://pecl.php.net/package/libevent */ class LibEventLoop implements LoopInterface { diff --git a/src/StreamSelectLoop.php b/src/StreamSelectLoop.php index 1cf6d1a3..d3498f2d 100644 --- a/src/StreamSelectLoop.php +++ b/src/StreamSelectLoop.php @@ -9,7 +9,14 @@ use React\EventLoop\Timer\Timers; /** - * A stream_select() based event-loop. + * A `stream_select()` based event loop. + * + * This uses the [`stream_select()`](http://php.net/manual/en/function.stream-select.php) + * function and is the only implementation which works out of the box with PHP. + * It does a simple `select` system call. + * It's not the most performant of loops, but still does the job quite well. + * + * @link http://php.net/manual/en/function.stream-select.php */ class StreamSelectLoop implements LoopInterface { From ffe26e93ff97a44762a5f7a8ca9f8957dced395f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Mon, 4 Dec 2017 09:52:14 +0100 Subject: [PATCH 3/3] Documentation for common event loop use cases --- README.md | 40 ++++++++++++++++++++++++++++++++++++++-- src/ExtEventLoop.php | 2 ++ src/LibEvLoop.php | 4 ++++ src/LibEventLoop.php | 7 +++++++ src/StreamSelectLoop.php | 27 +++++++++++++++++++++++++-- 5 files changed, 76 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 37e6de74..e9531a50 100644 --- a/README.md +++ b/README.md @@ -158,8 +158,31 @@ A `stream_select()` based event loop. This uses the [`stream_select()`](http://php.net/manual/en/function.stream-select.php) function and is the only implementation which works out of the box with PHP. -It does a simple `select` system call. -It's not the most performant of loops, but still does the job quite well. + +This event loop works out of the box on PHP 5.4 through PHP 7+ and HHVM. +This means that no installation is required and this library works on all +platforms and supported PHP versions. +Accordingly, the [`Factory`](#factory) will use this event loop by default if +you do not install any of the event loop extensions listed below. + +Under the hood, it does a simple `select` system call. +This system call is limited to the maximum file descriptor number of +`FD_SETSIZE` (platform dependent, commonly 1024) and scales with `O(m)` +(`m` being the maximum file descriptor number passed). +This means that you may run into issues when handling thousands of streams +concurrently and you may want to look into using one of the alternative +event loop implementations listed below in this case. +If your use case is among the many common use cases that involve handling only +dozens or a few hundred streams at once, then this event loop implementation +performs really well. + +If you want to use signal handling (see also [`addSignal()`](#addsignal) below), +this event loop implementation requires `ext-pcntl`. +This extension is only available for Unix-like platforms and does not support +Windows. +It is commonly installed as part of many PHP distributions. +If this extension is missing (or you're running on Windows), signal handling is +not supported and throws a `BadMethodCallException` instead. #### LibEventLoop @@ -168,6 +191,13 @@ An `ext-libevent` based event loop. This uses the [`libevent` PECL extension](https://pecl.php.net/package/libevent). `libevent` itself supports a number of system-specific backends (epoll, kqueue). +This event loop does only work with PHP 5. +An [unofficial update](https://github.com/php/pecl-event-libevent/pull/2) for +PHP 7 does exist, but it is known to cause regular crashes due to `SEGFAULT`s. +To reiterate: Using this event loop on PHP 7 is not recommended. +Accordingly, the [`Factory`](#factory) will not try to use this event loop on +PHP 7. + #### LibEvLoop An `ext-libev` based event loop. @@ -175,6 +205,10 @@ An `ext-libev` based event loop. This uses an [unofficial `libev` extension](https://github.com/m4rw3r/php-libev). It supports the same backends as libevent. +This loop does only work with PHP 5. +An update for PHP 7 is [unlikely](https://github.com/m4rw3r/php-libev/issues/8) +to happen any time soon. + #### ExtEventLoop An `ext-event` based event loop. @@ -182,6 +216,8 @@ An `ext-event` based event loop. This uses the [`event` PECL extension](https://pecl.php.net/package/event). It supports the same backends as libevent. +This loop is known to work with PHP 5.4 through PHP 7+. + ### LoopInterface #### addTimer() diff --git a/src/ExtEventLoop.php b/src/ExtEventLoop.php index eb08e9b3..73e7e97c 100644 --- a/src/ExtEventLoop.php +++ b/src/ExtEventLoop.php @@ -16,6 +16,8 @@ * This uses the [`event` PECL extension](https://pecl.php.net/package/event). * It supports the same backends as libevent. * + * This loop is known to work with PHP 5.4 through PHP 7+. + * * @link https://pecl.php.net/package/event */ class ExtEventLoop implements LoopInterface diff --git a/src/LibEvLoop.php b/src/LibEvLoop.php index 5dbaf62a..640c7da7 100644 --- a/src/LibEvLoop.php +++ b/src/LibEvLoop.php @@ -17,6 +17,10 @@ * This uses an [unofficial `libev` extension](https://github.com/m4rw3r/php-libev). * It supports the same backends as libevent. * + * This loop does only work with PHP 5. + * An update for PHP 7 is [unlikely](https://github.com/m4rw3r/php-libev/issues/8) + * to happen any time soon. + * * @see https://github.com/m4rw3r/php-libev * @see https://gist.github.com/1688204 */ diff --git a/src/LibEventLoop.php b/src/LibEventLoop.php index 2a1ee6aa..94cdbb01 100644 --- a/src/LibEventLoop.php +++ b/src/LibEventLoop.php @@ -15,6 +15,13 @@ * This uses the [`libevent` PECL extension](https://pecl.php.net/package/libevent). * `libevent` itself supports a number of system-specific backends (epoll, kqueue). * + * This event loop does only work with PHP 5. + * An [unofficial update](https://github.com/php/pecl-event-libevent/pull/2) for + * PHP 7 does exist, but it is known to cause regular crashes due to `SEGFAULT`s. + * To reiterate: Using this event loop on PHP 7 is not recommended. + * Accordingly, the [`Factory`](#factory) will not try to use this event loop on + * PHP 7. + * * @link https://pecl.php.net/package/libevent */ class LibEventLoop implements LoopInterface diff --git a/src/StreamSelectLoop.php b/src/StreamSelectLoop.php index d3498f2d..af46ea23 100644 --- a/src/StreamSelectLoop.php +++ b/src/StreamSelectLoop.php @@ -13,8 +13,31 @@ * * This uses the [`stream_select()`](http://php.net/manual/en/function.stream-select.php) * function and is the only implementation which works out of the box with PHP. - * It does a simple `select` system call. - * It's not the most performant of loops, but still does the job quite well. + * + * This event loop works out of the box on PHP 5.4 through PHP 7+ and HHVM. + * This means that no installation is required and this library works on all + * platforms and supported PHP versions. + * Accordingly, the [`Factory`](#factory) will use this event loop by default if + * you do not install any of the event loop extensions listed below. + * + * Under the hood, it does a simple `select` system call. + * This system call is limited to the maximum file descriptor number of + * `FD_SETSIZE` (platform dependent, commonly 1024) and scales with `O(m)` + * (`m` being the maximum file descriptor number passed). + * This means that you may run into issues when handling thousands of streams + * concurrently and you may want to look into using one of the alternative + * event loop implementations listed below in this case. + * If your use case is among the many common use cases that involve handling only + * dozens or a few hundred streams at once, then this event loop implementation + * performs really well. + * + * If you want to use signal handling (see also [`addSignal()`](#addsignal) below), + * this event loop implementation requires `ext-pcntl`. + * This extension is only available for Unix-like platforms and does not support + * Windows. + * It is commonly installed as part of many PHP distributions. + * If this extension is missing (or you're running on Windows), signal handling is + * not supported and throws a `BadMethodCallException` instead. * * @link http://php.net/manual/en/function.stream-select.php */