Skip to content

Commit 0307e73

Browse files
committed
Add static Loop methods
1 parent 01a2900 commit 0307e73

17 files changed

+497
-65
lines changed

README.md

Lines changed: 146 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ single [`run()`](#run) call that is controlled by the user.
1414
* [Quickstart example](#quickstart-example)
1515
* [Usage](#usage)
1616
* [Loop](#loop)
17+
* [Loop methods](#loop-methods)
1718
* [get()](#get)
1819
* [Factory](#factory)
1920
* [~~create()~~](#create)
@@ -52,35 +53,53 @@ use React\EventLoop\Loop;
5253
$server = stream_socket_server('tcp://127.0.0.1:8080');
5354
stream_set_blocking($server, false);
5455

55-
Loop::get()->addReadStream($server, function ($server) {
56+
Loop::addReadStream($server, function ($server) {
5657
$conn = stream_socket_accept($server);
5758
$data = "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nHi\n";
58-
Loop::get()->addWriteStream($conn, function ($conn) use (&$data) {
59+
Loop::addWriteStream($conn, function ($conn) use (&$data) {
5960
$written = fwrite($conn, $data);
6061
if ($written === strlen($data)) {
6162
fclose($conn);
62-
Loop::get()->removeWriteStream($conn);
63+
Loop::removeWriteStream($conn);
6364
} else {
6465
$data = substr($data, $written);
6566
}
6667
});
6768
});
6869

69-
Loop::get()->addPeriodicTimer(5, function () {
70+
Loop::addPeriodicTimer(5, function () {
7071
$memory = memory_get_usage() / 1024;
7172
$formatted = number_format($memory, 3).'K';
7273
echo "Current memory usage: {$formatted}\n";
7374
});
7475

75-
Loop::get()->run();
76+
Loop::run();
7677
```
7778

7879
See also the [examples](examples).
7980

8081
## Usage
8182

82-
Typical applications use a single event loop which is created at the beginning
83-
and run at the end of the program.
83+
As of `v1.2.0`, typical applications would use the [`Loop` object](#loop)
84+
to use the currently active event loop instance like this:
85+
86+
```php
87+
use React\EventLoop\Loop;
88+
89+
$timer = Loop::addPeriodicTimer(0.1, function () {
90+
echo "Tick" . PHP_EOL;
91+
});
92+
Loop::addTimer(1.0, function () use ($timer) {
93+
Loop::cancelTimer($timer);
94+
echo 'Done' . PHP_EOL;
95+
});
96+
97+
Loop::run();
98+
```
99+
100+
As an alternative, you can also explicitly create an event loop instance at the
101+
beginning, reuse it throughout your program and finally run it at the end of the
102+
program like this:
84103

85104
```php
86105
$loop = React\EventLoop\Loop::get(); // or deprecated React\EventLoop\Factory::create();
@@ -96,6 +115,9 @@ $loop->addTimer(1.0, function () use ($loop, $timer) {
96115
$loop->run();
97116
```
98117

118+
While the former is more concise, the latter is more explicit.
119+
In both cases, the program would perform the exact same steps.
120+
99121
1. The event loop instance is created at the beginning of the program. This is
100122
implicitly done the first time you call the [`Loop` class](#loop) or
101123
explicitly when using the deprecated [`Factory::create() method`](#create)
@@ -107,28 +129,137 @@ $loop->run();
107129
3. The event loop is run at the end of the program with a single [`run()`](#run)
108130
call at the end of the program.
109131

132+
As of `v1.2.0`, we highly recommend using the [`Loop` class](#loop).
133+
The explicit loop instructions are still valid and may still be useful in some
134+
applications, especially for a transition period towards the more concise style.
135+
110136
### Loop
111137

112138
The `Loop` class exists as a convenient global accessor for the event loop.
113139

114-
#### get()
140+
#### Loop methods
141+
142+
The `Loop` class provides all methods that exist on the [`LoopInterface`](#loopinterface)
143+
as static methods:
115144

116-
The `get(): LoopInterface` method is the preferred way to get and use the event loop. With
117-
it there is no need to always pass the loop around anymore.
145+
* [run()](#run)
146+
* [stop()](#stop)
147+
* [addTimer()](#addtimer)
148+
* [addPeriodicTimer()](#addperiodictimer)
149+
* [cancelTimer()](#canceltimer)
150+
* [futureTick()](#futuretick)
151+
* [addSignal()](#addsignal)
152+
* [removeSignal()](#removesignal)
153+
* [addReadStream()](#addreadstream)
154+
* [addWriteStream()](#addwritestream)
155+
* [removeReadStream()](#removereadstream)
156+
* [removeWriteStream()](#removewritestream)
157+
158+
If you're working with the event loop in your application code, it's often
159+
easiest to directly interface with the static methods defined on the `Loop` class
160+
like this:
118161

119162
```php
120163
use React\EventLoop\Loop;
121164

122-
Loop::get()->addTimer(0.02, function () {
123-
echo 'World!';
165+
$timer = Loop::addPeriodicTimer(0.1, function () {
166+
echo 'tick!' . PHP_EOL;
124167
});
125-
Loop::get()->addTimer(0.01, function () {
126-
echo 'Hello ';
168+
169+
Loop::addTimer(1.0, function () use ($timer) {
170+
Loop::cancelTimer($timer);
171+
echo 'Done' . PHP_EOL;
127172
});
128173

129-
Loop::get()->run();
174+
Loop::run();
130175
```
131176

177+
On the other hand, if you're familiar with object-oriented programming (OOP) and
178+
dependency injection (DI), you may want to inject an event loop instance and
179+
invoke instance methods on the `LoopInterface` like this:
180+
181+
```php
182+
use React\EventLoop\Loop;
183+
use React\EventLoop\LoopInterface;
184+
185+
class Greeter
186+
{
187+
private $loop;
188+
189+
public function __construct(LoopInterface $loop)
190+
{
191+
$this->loop = $loop;
192+
}
193+
194+
public function greet(string $name)
195+
{
196+
$this->loop->addTimer(1.0, function () use ($name) {
197+
echo 'Hello ' . $name . '!' . PHP_EOL;
198+
});
199+
}
200+
}
201+
202+
$greeter = new Greeter(Loop::get());
203+
$greeter->greet('Alice');
204+
$greeter->greet('Bob');
205+
206+
Loop::run();
207+
```
208+
209+
See [`LoopInterface`](#loopinterface) for more details about available methods.
210+
211+
#### get()
212+
213+
The `get(): LoopInterface` method can be used to
214+
get the currently active event loop instance.
215+
216+
This method will always return the same event loop instance throughout the
217+
lifetime of your application.
218+
219+
```php
220+
use React\EventLoop\Loop;
221+
use React\EventLoop\LoopInterface;
222+
223+
$loop = Loop::get();
224+
225+
assert($loop instanceof LoopInterface);
226+
assert($loop === Loop::get());
227+
```
228+
229+
This is particularly useful if you're using object-oriented programming (OOP)
230+
and dependency injection (DI). In this case, you may want to inject an event
231+
loop instance and invoke instance methods on the `LoopInterface` like this:
232+
233+
```php
234+
use React\EventLoop\Loop;
235+
use React\EventLoop\LoopInterface;
236+
237+
class Greeter
238+
{
239+
private $loop;
240+
241+
public function __construct(LoopInterface $loop)
242+
{
243+
$this->loop = $loop;
244+
}
245+
246+
public function greet(string $name)
247+
{
248+
$this->loop->addTimer(1.0, function () use ($name) {
249+
echo 'Hello ' . $name . '!' . PHP_EOL;
250+
});
251+
}
252+
}
253+
254+
$greeter = new Greeter(Loop::get());
255+
$greeter->greet('Alice');
256+
$greeter->greet('Bob');
257+
258+
Loop::run();
259+
```
260+
261+
See [`LoopInterface`](#loopinterface) for more details about available methods.
262+
132263
### Factory
133264

134265
The `Factory` class exists as a convenient way to pick the best available

examples/01-timers.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44

55
require __DIR__ . '/../vendor/autoload.php';
66

7-
Loop::get()->addTimer(0.8, function () {
7+
Loop::addTimer(0.8, function () {
88
echo 'world!' . PHP_EOL;
99
});
1010

11-
Loop::get()->addTimer(0.3, function () {
11+
Loop::addTimer(0.3, function () {
1212
echo 'hello ';
1313
});
1414

15-
Loop::get()->run();
15+
Loop::run();

examples/02-periodic.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44

55
require __DIR__ . '/../vendor/autoload.php';
66

7-
$timer = Loop::get()->addPeriodicTimer(0.1, function () {
7+
$timer = Loop::addPeriodicTimer(0.1, function () {
88
echo 'tick!' . PHP_EOL;
99
});
1010

11-
Loop::get()->addTimer(1.0, function () use ($timer) {
12-
Loop::get()->cancelTimer($timer);
11+
Loop::addTimer(1.0, function () use ($timer) {
12+
Loop::cancelTimer($timer);
1313
echo 'Done' . PHP_EOL;
1414
});
1515

16-
Loop::get()->run();
16+
Loop::run();

examples/03-ticks.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44

55
require __DIR__ . '/../vendor/autoload.php';
66

7-
Loop::get()->futureTick(function () {
7+
Loop::futureTick(function () {
88
echo 'b';
99
});
10-
Loop::get()->futureTick(function () {
10+
Loop::futureTick(function () {
1111
echo 'c';
1212
});
1313
echo 'a';
1414

15-
Loop::get()->run();
15+
Loop::run();

examples/04-signals.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
exit(1);
1010
}
1111

12-
Loop::get()->addSignal(SIGINT, $func = function ($signal) use (&$func) {
12+
Loop::addSignal(SIGINT, $func = function ($signal) use (&$func) {
1313
echo 'Signal: ', (string)$signal, PHP_EOL;
14-
Loop::get()->removeSignal(SIGINT, $func);
14+
Loop::removeSignal(SIGINT, $func);
1515
});
1616

1717
echo 'Listening for SIGINT. Use "kill -SIGINT ' . getmypid() . '" or CTRL+C' . PHP_EOL;
1818

19-
Loop::get()->run();
19+
Loop::run();

examples/11-consume-stdin.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111

1212
// read everything from STDIN and report number of bytes
1313
// for illustration purposes only, should use react/stream instead
14-
Loop::get()->addReadStream(STDIN, function ($stream) {
14+
Loop::addReadStream(STDIN, function ($stream) {
1515
$chunk = fread($stream, 64 * 1024);
1616

1717
// reading nothing means we reached EOF
1818
if ($chunk === '') {
19-
Loop::get()->removeReadStream($stream);
19+
Loop::removeReadStream($stream);
2020
stream_set_blocking($stream, true);
2121
fclose($stream);
2222
return;
@@ -25,4 +25,4 @@
2525
echo strlen($chunk) . ' bytes' . PHP_EOL;
2626
});
2727

28-
Loop::get()->run();
28+
Loop::run();

examples/12-generate-yes.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717

1818
// write data to STDOUT whenever its write buffer accepts data
1919
// for illustrations purpose only, should use react/stream instead
20-
Loop::get()->addWriteStream(STDOUT, function ($stdout) use (&$data) {
20+
Loop::addWriteStream(STDOUT, function ($stdout) use (&$data) {
2121
// try to write data
2222
$r = fwrite($stdout, $data);
2323

2424
// nothing could be written despite being writable => closed
2525
if ($r === 0) {
26-
Loop::get()->removeWriteStream($stdout);
26+
Loop::removeWriteStream($stdout);
2727
fclose($stdout);
2828
stream_set_blocking($stdout, true);
2929
fwrite(STDERR, 'Stopped because STDOUT closed' . PHP_EOL);
@@ -38,4 +38,4 @@
3838
}
3939
});
4040

41-
Loop::get()->run();
41+
Loop::run();

examples/13-http-client-blocking.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,18 @@
1616
fwrite($stream, "GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n");
1717

1818
// wait for HTTP response
19-
Loop::get()->addReadStream($stream, function ($stream) {
19+
Loop::addReadStream($stream, function ($stream) {
2020
$chunk = fread($stream, 64 * 1024);
2121

2222
// reading nothing means we reached EOF
2323
if ($chunk === '') {
2424
echo '[END]' . PHP_EOL;
25-
Loop::get()->removeReadStream($stream);
25+
Loop::removeReadStream($stream);
2626
fclose($stream);
2727
return;
2828
}
2929

3030
echo $chunk;
3131
});
3232

33-
Loop::get()->run();
33+
Loop::run();

examples/14-http-client-async.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@
2323

2424
// print progress every 10ms
2525
echo 'Connecting';
26-
$timer = Loop::get()->addPeriodicTimer(0.01, function () {
26+
$timer = Loop::addPeriodicTimer(0.01, function () {
2727
echo '.';
2828
});
2929

3030
// wait for connection success/error
31-
Loop::get()->addWriteStream($stream, function ($stream) use ($timer) {
32-
Loop::get()->removeWriteStream($stream);
33-
Loop::get()->cancelTimer($timer);
31+
Loop::addWriteStream($stream, function ($stream) use ($timer) {
32+
Loop::removeWriteStream($stream);
33+
Loop::cancelTimer($timer);
3434

3535
// check for socket error (connection rejected)
3636
if (stream_socket_get_name($stream, true) === false) {
@@ -44,13 +44,13 @@
4444
fwrite($stream, "GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n");
4545

4646
// wait for HTTP response
47-
Loop::get()->addReadStream($stream, function ($stream) {
47+
Loop::addReadStream($stream, function ($stream) {
4848
$chunk = fread($stream, 64 * 1024);
4949

5050
// reading nothing means we reached EOF
5151
if ($chunk === '') {
5252
echo '[END]' . PHP_EOL;
53-
Loop::get()->removeReadStream($stream);
53+
Loop::removeReadStream($stream);
5454
fclose($stream);
5555
return;
5656
}
@@ -59,4 +59,4 @@
5959
});
6060
});
6161

62-
Loop::get()->run();
62+
Loop::run();

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy