Event loop abstraction layer that libraries can use for evented I/O.
Table of Contents
Here is an async HTTP server built with just the event loop.
$loop = React\EventLoop\Factory::create();
$server = stream_socket_server('tcp://127.0.0.1:8080');
stream_set_blocking($server, 0);
$loop->addReadStream($server, function ($server) use ($loop) {
$conn = stream_socket_accept($server);
$data = "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nHi\n";
$loop->addWriteStream($conn, function ($conn) use (&$data, $loop) {
$written = fwrite($conn, $data);
if ($written === strlen($data)) {
fclose($conn);
$loop->removeStream($conn);
} else {
$data = substr($data, $written);
}
});
});
$loop->addPeriodicTimer(5, function () {
$memory = memory_get_usage() / 1024;
$formatted = number_format($memory, 3).'K';
echo "Current memory usage: {$formatted}\n";
});
$loop->run();
In order for async based libraries to be interoperable, they need to use the
same event loop. This component provides a common LoopInterface
that any
library can target. This allows them to be used in the same loop, with one
single run()
call that is controlled by the user.
// [1]
$loop = React\EventLoop\Factory::create();
// [2]
$loop->addPeriodicTimer(1, function () {
echo "Tick\n";
});
$stream = new React\Stream\ReadableResourceStream(
fopen('file.txt', 'r'),
$loop
);
// [3]
$loop->run();
- The loop instance is created at the beginning of the program. A convenience
factory
React\EventLoop\Factory::create()
is provided by this library which picks the best available loop implementation. - The loop instance is used directly or passed to library and application code.
In this example, a periodic timer is registered with the event loop which
simply outputs
Tick
every second and a readable stream is created by using ReactPHP's stream component for demonstration purposes. - The loop is run with a single
$loop->run()
call at the end of the program.
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 simpleselect
system call. It's not the most performant of loops, but still does the job quite well. -
LibEventLoop
: This uses thelibevent
pecl extension.libevent
itself supports a number of system-specific backends (epoll, kqueue). -
LibEvLoop
: This uses thelibev
pecl extension (github). It supports the same backends as libevent. -
ExtEventLoop
: This uses theevent
pecl extension. It supports the same backends as libevent.
All of the loops support these features:
- File descriptor polling
- One-off timers
- Periodic timers
- Deferred execution of callbacks
The recommended way to install this library is through Composer. New to Composer?
This will install the latest supported version:
$ composer require react/event-loop
To run the test suite, you first need to clone this repo and then install all dependencies through Composer:
$ composer install
To run the test suite, go to the project root and run:
$ php vendor/bin/phpunit
MIT, see LICENSE file.