Skip to content

Commit 55ee80d

Browse files
authored
Merge pull request #127 from clue-labs/loops
Documentation for event loop implementations
2 parents e0d7c07 + ffe26e9 commit 55ee80d

File tree

6 files changed

+190
-40
lines changed

6 files changed

+190
-40
lines changed

README.md

+126-34
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,25 @@ For the code of the current stable 0.4.x release, checkout the
1818

1919
* [Quickstart example](#quickstart-example)
2020
* [Usage](#usage)
21-
* [Loop implementations](#loop-implementations)
21+
* [Factory](#factory)
22+
* [create()](#create)
23+
* [Loop implementations](#loop-implementations)
24+
* [StreamSelectLoop](#streamselectloop)
25+
* [LibEventLoop](#libeventloop)
26+
* [LibEvLoop](#libevloop)
27+
* [ExtEventLoop](#exteventloop)
28+
* [LoopInterface](#loopinterface)
29+
* [addtimer()](#addtimer)
30+
* [addPeriodicTimer()](#addperiodictimer)
31+
* [cancelTimer()](#canceltimer)
32+
* [isTimerActive()](#istimeractive)
33+
* [futureTick()](#futuretick)
34+
* [addSignal()](#addsignal)
35+
* [removeSignal()](#removesignal)
36+
* [addReadStream()](#addreadstream)
37+
* [addWriteStream()](#addwritestream)
38+
* [removeReadStream()](#removereadstream)
39+
* [removeWriteStream()](#removewritestream)
2240
* [Install](#install)
2341
* [Tests](#tests)
2442
* [License](#license)
@@ -94,49 +112,115 @@ $loop->run();
94112
purposes.
95113
3. The loop is run with a single `$loop->run()` call at the end of the program.
96114

97-
## Factory
115+
### Factory
98116

99117
The `Factory` class exists as a convenient way to pick the best available
100-
[loop implementation](#loop-implementations).
118+
[event loop implementation](#loop-implementations).
101119

102-
The `create(): LoopInterface` method can be used to create a new loop
120+
#### create()
121+
122+
The `create(): LoopInterface` method can be used to create a new event loop
103123
instance:
104124

105125
```php
106126
$loop = React\EventLoop\Factory::create();
107127
```
108128

109-
This method always returns an instance implementing `LoopInterface`,
110-
the actual loop implementation is an implementation detail.
129+
This method always returns an instance implementing [`LoopInterface`](#loopinterface),
130+
the actual [event loop implementation](#loop-implementations) is an implementation detail.
111131

112132
This method should usually only be called once at the beginning of the program.
113133

114-
## Loop implementations
115-
116-
In addition to the interface there are the following implementations provided:
117-
118-
* `StreamSelectLoop`: This is the only implementation which works out of the
119-
box with PHP. It does a simple `select` system call. It's not the most
120-
performant of loops, but still does the job quite well.
121-
122-
* `LibEventLoop`: This uses the `libevent` pecl extension. `libevent` itself
123-
supports a number of system-specific backends (epoll, kqueue).
134+
### Loop implementations
124135

125-
* `LibEvLoop`: This uses the `libev` pecl extension
126-
([github](https://github.com/m4rw3r/php-libev)). It supports the same
127-
backends as libevent.
136+
In addition to the [`LoopInterface`](#loopinterface), there are a number of
137+
event loop implementations provided.
128138

129-
* `ExtEventLoop`: This uses the `event` pecl extension. It supports the same
130-
backends as libevent.
131-
132-
All of the loops support these features:
139+
All of the event loops support these features:
133140

134141
* File descriptor polling
135142
* One-off timers
136143
* Periodic timers
137144
* Deferred execution on future loop tick
138145

139-
### addTimer()
146+
For most consumers of this package, the underlying event loop implementation is
147+
an implementation detail.
148+
You should use the [`Factory`](#factory) to automatically create a new instance.
149+
150+
Advanced! If you explicitly need a certain event loop implementation, you can
151+
manually instantiate one of the following classes.
152+
Note that you may have to install the required PHP extensions for the respective
153+
event loop implementation first or this may result in a fatal error.
154+
155+
#### StreamSelectLoop
156+
157+
A `stream_select()` based event loop.
158+
159+
This uses the [`stream_select()`](http://php.net/manual/en/function.stream-select.php)
160+
function and is the only implementation which works out of the box with PHP.
161+
162+
This event loop works out of the box on PHP 5.4 through PHP 7+ and HHVM.
163+
This means that no installation is required and this library works on all
164+
platforms and supported PHP versions.
165+
Accordingly, the [`Factory`](#factory) will use this event loop by default if
166+
you do not install any of the event loop extensions listed below.
167+
168+
Under the hood, it does a simple `select` system call.
169+
This system call is limited to the maximum file descriptor number of
170+
`FD_SETSIZE` (platform dependent, commonly 1024) and scales with `O(m)`
171+
(`m` being the maximum file descriptor number passed).
172+
This means that you may run into issues when handling thousands of streams
173+
concurrently and you may want to look into using one of the alternative
174+
event loop implementations listed below in this case.
175+
If your use case is among the many common use cases that involve handling only
176+
dozens or a few hundred streams at once, then this event loop implementation
177+
performs really well.
178+
179+
If you want to use signal handling (see also [`addSignal()`](#addsignal) below),
180+
this event loop implementation requires `ext-pcntl`.
181+
This extension is only available for Unix-like platforms and does not support
182+
Windows.
183+
It is commonly installed as part of many PHP distributions.
184+
If this extension is missing (or you're running on Windows), signal handling is
185+
not supported and throws a `BadMethodCallException` instead.
186+
187+
#### LibEventLoop
188+
189+
An `ext-libevent` based event loop.
190+
191+
This uses the [`libevent` PECL extension](https://pecl.php.net/package/libevent).
192+
`libevent` itself supports a number of system-specific backends (epoll, kqueue).
193+
194+
This event loop does only work with PHP 5.
195+
An [unofficial update](https://github.com/php/pecl-event-libevent/pull/2) for
196+
PHP 7 does exist, but it is known to cause regular crashes due to `SEGFAULT`s.
197+
To reiterate: Using this event loop on PHP 7 is not recommended.
198+
Accordingly, the [`Factory`](#factory) will not try to use this event loop on
199+
PHP 7.
200+
201+
#### LibEvLoop
202+
203+
An `ext-libev` based event loop.
204+
205+
This uses an [unofficial `libev` extension](https://github.com/m4rw3r/php-libev).
206+
It supports the same backends as libevent.
207+
208+
This loop does only work with PHP 5.
209+
An update for PHP 7 is [unlikely](https://github.com/m4rw3r/php-libev/issues/8)
210+
to happen any time soon.
211+
212+
#### ExtEventLoop
213+
214+
An `ext-event` based event loop.
215+
216+
This uses the [`event` PECL extension](https://pecl.php.net/package/event).
217+
It supports the same backends as libevent.
218+
219+
This loop is known to work with PHP 5.4 through PHP 7+.
220+
221+
### LoopInterface
222+
223+
#### addTimer()
140224

141225
The `addTimer(float $interval, callable $callback): TimerInterface` method can be used to
142226
enqueue a callback to be invoked once after the given interval.
@@ -183,7 +267,7 @@ hello('Tester', $loop);
183267
The execution order of timers scheduled to execute at the same time is
184268
not guaranteed.
185269

186-
### addPeriodicTimer()
270+
#### addPeriodicTimer()
187271

188272
The `addPeriodicTimer(float $interval, callable $callback): TimerInterface` method can be used to
189273
enqueue a callback to be invoked repeatedly after the given interval.
@@ -237,7 +321,7 @@ hello('Tester', $loop);
237321
The execution order of timers scheduled to execute at the same time is
238322
not guaranteed.
239323

240-
### cancelTimer()
324+
#### cancelTimer()
241325

242326
The `cancelTimer(TimerInterface $timer): void` method can be used to
243327
cancel a pending timer.
@@ -252,7 +336,7 @@ Calling this method on a timer instance that has not been added to this
252336
loop instance or on a timer that is not "active" (or has already been
253337
cancelled) has no effect.
254338

255-
### isTimerActive()
339+
#### isTimerActive()
256340

257341
The `isTimerActive(TimerInterface $timer): bool` method can be used to
258342
check if a given timer is active.
@@ -262,7 +346,7 @@ via [`addTimer()`](#addtimer) or [`addPeriodicTimer()`](#addperiodictimer)
262346
and has not been cancelled via [`cancelTimer()`](#canceltimer) and is not
263347
a non-periodic timer that has already been triggered after its interval.
264348

265-
### futureTick()
349+
#### futureTick()
266350

267351
The `futureTick(callable $listener): void` method can be used to
268352
schedule a callback to be invoked on a future tick of the event loop.
@@ -310,7 +394,7 @@ echo 'a';
310394

311395
See also [example #3](examples).
312396

313-
### addSignal()
397+
#### addSignal()
314398

315399
The `addSignal(int $signal, callable $listener): void` method can be used to
316400
register a listener to be notified when a signal has been caught by this process.
@@ -344,7 +428,7 @@ missing.
344428
**Note: A listener can only be added once to the same signal, any
345429
attempts to add it more then once will be ignored.**
346430

347-
### removeSignal()
431+
#### removeSignal()
348432

349433
The `removeSignal(int $signal, callable $listener): void` method can be used to
350434
remove a previously added signal listener.
@@ -355,7 +439,7 @@ $loop->removeSignal(SIGINT, $listener);
355439

356440
Any attempts to remove listeners that aren't registered will be ignored.
357441

358-
### addReadStream()
442+
#### addReadStream()
359443

360444
> Advanced! Note that this low-level API is considered advanced usage.
361445
Most use cases should probably use the higher-level
@@ -398,7 +482,7 @@ read event listener for this stream.
398482
The execution order of listeners when multiple streams become ready at
399483
the same time is not guaranteed.
400484

401-
### addWriteStream()
485+
#### addWriteStream()
402486

403487
> Advanced! Note that this low-level API is considered advanced usage.
404488
Most use cases should probably use the higher-level
@@ -441,15 +525,15 @@ write event listener for this stream.
441525
The execution order of listeners when multiple streams become ready at
442526
the same time is not guaranteed.
443527

444-
### removeReadStream()
528+
#### removeReadStream()
445529

446530
The `removeReadStream(resource $stream): void` method can be used to
447531
remove the read event listener for the given stream.
448532

449533
Removing a stream from the loop that has already been removed or trying
450534
to remove a stream that was never added or is invalid has no effect.
451535

452-
### removeWriteStream()
536+
#### removeWriteStream()
453537

454538
The `removeWriteStream(resource $stream): void` method can be used to
455539
remove the write event listener for the given stream.
@@ -468,6 +552,14 @@ This will install the latest supported version:
468552
$ composer require react/event-loop
469553
```
470554

555+
This project aims to run on any platform and thus does not require any PHP
556+
extensions and supports running on legacy PHP 5.4 through current PHP 7+ and
557+
HHVM.
558+
It's *highly recommended to use PHP 7+* for this project.
559+
560+
Installing any of the event loop extensions is suggested, but entirely optional.
561+
See also [event loop implementations](#loop-implementations) for more details.
562+
471563
## Tests
472564

473565
To run the test suite, you first need to clone this repo and then install all

src/ExtEventLoop.php

+8-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,14 @@
1111
use SplObjectStorage;
1212

1313
/**
14-
* An ext-event based event-loop.
14+
* An `ext-event` based event loop.
15+
*
16+
* This uses the [`event` PECL extension](https://pecl.php.net/package/event).
17+
* It supports the same backends as libevent.
18+
*
19+
* This loop is known to work with PHP 5.4 through PHP 7+.
20+
*
21+
* @link https://pecl.php.net/package/event
1522
*/
1623
class ExtEventLoop implements LoopInterface
1724
{

src/Factory.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@
33
namespace React\EventLoop;
44

55
/**
6-
* The `Factory` class exists as a convenient way to pick the best available loop implementation.
6+
* The `Factory` class exists as a convenient way to pick the best available event loop implementation.
77
*/
88
class Factory
99
{
1010
/**
11-
* Creates a new loop instance
11+
* Creates a new event loop instance
1212
*
1313
* ```php
1414
* $loop = React\EventLoop\Factory::create();
1515
* ```
1616
*
1717
* This method always returns an instance implementing `LoopInterface`,
18-
* the actual loop implementation is an implementation detail.
18+
* the actual event loop implementation is an implementation detail.
1919
*
2020
* This method should usually only be called once at the beginning of the program.
2121
*

src/LibEvLoop.php

+9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@
1212
use SplObjectStorage;
1313

1414
/**
15+
* An `ext-libev` based event loop.
16+
*
17+
* This uses an [unofficial `libev` extension](https://github.com/m4rw3r/php-libev).
18+
* It supports the same backends as libevent.
19+
*
20+
* This loop does only work with PHP 5.
21+
* An update for PHP 7 is [unlikely](https://github.com/m4rw3r/php-libev/issues/8)
22+
* to happen any time soon.
23+
*
1524
* @see https://github.com/m4rw3r/php-libev
1625
* @see https://gist.github.com/1688204
1726
*/

src/LibEventLoop.php

+13-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,19 @@
1010
use SplObjectStorage;
1111

1212
/**
13-
* An ext-libevent based event-loop.
13+
* An `ext-libevent` based event loop.
14+
*
15+
* This uses the [`libevent` PECL extension](https://pecl.php.net/package/libevent).
16+
* `libevent` itself supports a number of system-specific backends (epoll, kqueue).
17+
*
18+
* This event loop does only work with PHP 5.
19+
* An [unofficial update](https://github.com/php/pecl-event-libevent/pull/2) for
20+
* PHP 7 does exist, but it is known to cause regular crashes due to `SEGFAULT`s.
21+
* To reiterate: Using this event loop on PHP 7 is not recommended.
22+
* Accordingly, the [`Factory`](#factory) will not try to use this event loop on
23+
* PHP 7.
24+
*
25+
* @link https://pecl.php.net/package/libevent
1426
*/
1527
class LibEventLoop implements LoopInterface
1628
{

src/StreamSelectLoop.php

+31-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,37 @@
99
use React\EventLoop\Timer\Timers;
1010

1111
/**
12-
* A stream_select() based event-loop.
12+
* A `stream_select()` based event loop.
13+
*
14+
* This uses the [`stream_select()`](http://php.net/manual/en/function.stream-select.php)
15+
* function and is the only implementation which works out of the box with PHP.
16+
*
17+
* This event loop works out of the box on PHP 5.4 through PHP 7+ and HHVM.
18+
* This means that no installation is required and this library works on all
19+
* platforms and supported PHP versions.
20+
* Accordingly, the [`Factory`](#factory) will use this event loop by default if
21+
* you do not install any of the event loop extensions listed below.
22+
*
23+
* Under the hood, it does a simple `select` system call.
24+
* This system call is limited to the maximum file descriptor number of
25+
* `FD_SETSIZE` (platform dependent, commonly 1024) and scales with `O(m)`
26+
* (`m` being the maximum file descriptor number passed).
27+
* This means that you may run into issues when handling thousands of streams
28+
* concurrently and you may want to look into using one of the alternative
29+
* event loop implementations listed below in this case.
30+
* If your use case is among the many common use cases that involve handling only
31+
* dozens or a few hundred streams at once, then this event loop implementation
32+
* performs really well.
33+
*
34+
* If you want to use signal handling (see also [`addSignal()`](#addsignal) below),
35+
* this event loop implementation requires `ext-pcntl`.
36+
* This extension is only available for Unix-like platforms and does not support
37+
* Windows.
38+
* It is commonly installed as part of many PHP distributions.
39+
* If this extension is missing (or you're running on Windows), signal handling is
40+
* not supported and throws a `BadMethodCallException` instead.
41+
*
42+
* @link http://php.net/manual/en/function.stream-select.php
1343
*/
1444
class StreamSelectLoop implements LoopInterface
1545
{

0 commit comments

Comments
 (0)