@@ -14,6 +14,7 @@ single [`run()`](#run) call that is controlled by the user.
14
14
* [ Quickstart example] ( #quickstart-example )
15
15
* [ Usage] ( #usage )
16
16
* [ Loop] ( #loop )
17
+ * [ Loop methods] ( #loop-methods )
17
18
* [ get()] ( #get )
18
19
* [ Factory] ( #factory )
19
20
* [ create()] ( #create )
@@ -52,88 +53,215 @@ use React\EventLoop\Loop;
52
53
$server = stream_socket_server('tcp://127.0.0.1:8080');
53
54
stream_set_blocking($server, false);
54
55
55
- Loop::get()-> addReadStream($server, function ($server) {
56
+ Loop::addReadStream($server, function ($server) {
56
57
$conn = stream_socket_accept($server);
57
58
$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) {
59
60
$written = fwrite($conn, $data);
60
61
if ($written === strlen($data)) {
61
62
fclose($conn);
62
- Loop::get()-> removeWriteStream($conn);
63
+ Loop::removeWriteStream($conn);
63
64
} else {
64
65
$data = substr($data, $written);
65
66
}
66
67
});
67
68
});
68
69
69
- Loop::get()-> addPeriodicTimer(5, function () {
70
+ Loop::addPeriodicTimer(5, function () {
70
71
$memory = memory_get_usage() / 1024;
71
72
$formatted = number_format($memory, 3).'K';
72
73
echo "Current memory usage: {$formatted}\n";
73
74
});
74
75
75
- Loop::get()-> run();
76
+ Loop::run();
76
77
```
77
78
78
79
See also the [ examples] ( examples ) .
79
80
80
81
## Usage
81
82
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:
84
85
85
86
``` php
86
- // [1]
87
- $loop = React\EventLoop\Factory::create();
87
+ use React\EventLoop\Loop;
88
88
89
- // [2]
90
- $loop->addPeriodicTimer(1, function () {
91
- echo "Tick\n";
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;
92
95
});
93
96
94
- $stream = new React\Stream\ReadableResourceStream(
95
- fopen('file.txt', 'r'),
96
- $loop
97
- );
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:
103
+
104
+ ``` php
105
+ $loop = React\EventLoop\Loop::get(); // or deprecated React\EventLoop\Factory::create();
106
+
107
+ $timer = $loop->addPeriodicTimer(0.1, function () {
108
+ echo "Tick" . PHP_EOL;
109
+ });
110
+ $loop->addTimer(1.0, function () use ($loop, $timer) {
111
+ $loop->cancelTimer($timer);
112
+ echo 'Done' . PHP_EOL;
113
+ });
98
114
99
- // [3]
100
115
$loop->run();
101
116
```
102
117
103
- 1 . The loop instance is created at the beginning of the program. A convenience
104
- factory [ ` React\EventLoop\Factory::create() ` ] ( #create ) is provided by this library which
105
- picks the best available [ loop implementation] ( #loop-implementations ) .
106
- 2 . The loop instance is used directly or passed to library and application code.
107
- In this example, a periodic timer is registered with the event loop which
108
- simply outputs ` Tick ` every second and a
109
- [ readable stream] ( https://github.com/reactphp/stream#readableresourcestream )
110
- is created by using ReactPHP's
111
- [ stream component] ( https://github.com/reactphp/stream ) for demonstration
112
- purposes.
113
- 3 . The loop is run with a single [ ` $loop->run() ` ] ( #run ) call at the end of the program.
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
+
121
+ 1 . The event loop instance is created at the beginning of the program. This is
122
+ implicitly done the first time you call the [ ` Loop ` class] ( #loop ) or
123
+ explicitly when using the deprecated [ ` Factory::create() method ` ] ( #create )
124
+ (or manually instantiating any of the [ loop implementation] ( #loop-implementations ) ).
125
+ 2 . The event loop is used directly or passed as an instance to library and
126
+ application code. In this example, a periodic timer is registered with the
127
+ event loop which simply outputs ` Tick ` every fraction of a second until another
128
+ timer stops the periodic timer after a second.
129
+ 3 . The event loop is run at the end of the program with a single [ ` run() ` ] ( #run )
130
+ call at the end of the program.
131
+
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.
114
135
115
136
### Loop
116
137
117
138
The ` Loop ` class exists as a convenient global accessor for the event loop.
118
139
119
- #### get()
140
+ #### Loop methods
120
141
121
- The ` get(): LoopInterface ` method is the preferred way to get and use the event loop. With
122
- it there is no need to always pass the loop around anymore.
142
+ The ` Loop ` class provides all methods that exist on the [ ` LoopInterface ` ] ( #loopinterface )
143
+ as static methods:
144
+
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:
123
161
124
162
``` php
125
163
use React\EventLoop\Loop;
126
164
127
- Loop::get()->addTimer(0.02 , function () {
128
- echo 'World!' ;
165
+ $timer = Loop::addPeriodicTimer(0.1 , function () {
166
+ echo 'tick!' . PHP_EOL ;
129
167
});
130
- Loop::get()->addTimer(0.01, function () {
131
- echo 'Hello ';
168
+
169
+ Loop::addTimer(1.0, function () use ($timer) {
170
+ Loop::cancelTimer($timer);
171
+ echo 'Done' . PHP_EOL;
132
172
});
133
173
134
- Loop::get()-> run();
174
+ Loop::run();
135
175
```
136
176
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
+ Each static method call will be forwarded as-is to the underlying event loop
210
+ instance by using the [ ` Loop::get() ` ] ( #get ) call internally.
211
+ See [ ` LoopInterface ` ] ( #loopinterface ) for more details about available methods.
212
+
213
+ #### get()
214
+
215
+ The ` get(): LoopInterface ` method can be used to
216
+ get the currently active event loop instance.
217
+
218
+ This method will always return the same event loop instance throughout the
219
+ lifetime of your application.
220
+
221
+ ``` php
222
+ use React\EventLoop\Loop;
223
+ use React\EventLoop\LoopInterface;
224
+
225
+ $loop = Loop::get();
226
+
227
+ assert($loop instanceof LoopInterface);
228
+ assert($loop === Loop::get());
229
+ ```
230
+
231
+ This is particularly useful if you're using object-oriented programming (OOP)
232
+ and dependency injection (DI). In this case, you may want to inject an event
233
+ loop instance and invoke instance methods on the ` LoopInterface ` like this:
234
+
235
+ ``` php
236
+ use React\EventLoop\Loop;
237
+ use React\EventLoop\LoopInterface;
238
+
239
+ class Greeter
240
+ {
241
+ private $loop;
242
+
243
+ public function __construct(LoopInterface $loop)
244
+ {
245
+ $this->loop = $loop;
246
+ }
247
+
248
+ public function greet(string $name)
249
+ {
250
+ $this->loop->addTimer(1.0, function () use ($name) {
251
+ echo 'Hello ' . $name . '!' . PHP_EOL;
252
+ });
253
+ }
254
+ }
255
+
256
+ $greeter = new Greeter(Loop::get());
257
+ $greeter->greet('Alice');
258
+ $greeter->greet('Bob');
259
+
260
+ Loop::run();
261
+ ```
262
+
263
+ See [ ` LoopInterface ` ] ( #loopinterface ) for more details about available methods.
264
+
137
265
### Factory
138
266
139
267
The ` Factory ` class exists as a convenient way to pick the best available
0 commit comments