1<?php 2 3namespace React\EventLoop; 4 5interface LoopInterface 6{ 7 /** 8 * [Advanced] Register a listener to be notified when a stream is ready to read. 9 * 10 * Note that this low-level API is considered advanced usage. 11 * Most use cases should probably use the higher-level 12 * [readable Stream API](https://github.com/reactphp/stream#readablestreaminterface) 13 * instead. 14 * 15 * The first parameter MUST be a valid stream resource that supports 16 * checking whether it is ready to read by this loop implementation. 17 * A single stream resource MUST NOT be added more than once. 18 * Instead, either call [`removeReadStream()`](#removereadstream) first or 19 * react to this event with a single listener and then dispatch from this 20 * listener. This method MAY throw an `Exception` if the given resource type 21 * is not supported by this loop implementation. 22 * 23 * The listener callback function MUST be able to accept a single parameter, 24 * the stream resource added by this method or you MAY use a function which 25 * has no parameters at all. 26 * 27 * The listener callback function MUST NOT throw an `Exception`. 28 * The return value of the listener callback function will be ignored and has 29 * no effect, so for performance reasons you're recommended to not return 30 * any excessive data structures. 31 * 32 * If you want to access any variables within your callback function, you 33 * can bind arbitrary data to a callback closure like this: 34 * 35 * ```php 36 * $loop->addReadStream($stream, function ($stream) use ($name) { 37 * echo $name . ' said: ' . fread($stream); 38 * }); 39 * ``` 40 * 41 * See also [example #11](examples). 42 * 43 * You can invoke [`removeReadStream()`](#removereadstream) to remove the 44 * read event listener for this stream. 45 * 46 * The execution order of listeners when multiple streams become ready at 47 * the same time is not guaranteed. 48 * 49 * @param resource $stream The PHP stream resource to check. 50 * @param callable $listener Invoked when the stream is ready. 51 * @throws \Exception if the given resource type is not supported by this loop implementation 52 * @see self::removeReadStream() 53 */ 54 public function addReadStream($stream, $listener); 55 56 /** 57 * [Advanced] Register a listener to be notified when a stream is ready to write. 58 * 59 * Note that this low-level API is considered advanced usage. 60 * Most use cases should probably use the higher-level 61 * [writable Stream API](https://github.com/reactphp/stream#writablestreaminterface) 62 * instead. 63 * 64 * The first parameter MUST be a valid stream resource that supports 65 * checking whether it is ready to write by this loop implementation. 66 * A single stream resource MUST NOT be added more than once. 67 * Instead, either call [`removeWriteStream()`](#removewritestream) first or 68 * react to this event with a single listener and then dispatch from this 69 * listener. This method MAY throw an `Exception` if the given resource type 70 * is not supported by this loop implementation. 71 * 72 * The listener callback function MUST be able to accept a single parameter, 73 * the stream resource added by this method or you MAY use a function which 74 * has no parameters at all. 75 * 76 * The listener callback function MUST NOT throw an `Exception`. 77 * The return value of the listener callback function will be ignored and has 78 * no effect, so for performance reasons you're recommended to not return 79 * any excessive data structures. 80 * 81 * If you want to access any variables within your callback function, you 82 * can bind arbitrary data to a callback closure like this: 83 * 84 * ```php 85 * $loop->addWriteStream($stream, function ($stream) use ($name) { 86 * fwrite($stream, 'Hello ' . $name); 87 * }); 88 * ``` 89 * 90 * See also [example #12](examples). 91 * 92 * You can invoke [`removeWriteStream()`](#removewritestream) to remove the 93 * write event listener for this stream. 94 * 95 * The execution order of listeners when multiple streams become ready at 96 * the same time is not guaranteed. 97 * 98 * Some event loop implementations are known to only trigger the listener if 99 * the stream *becomes* readable (edge-triggered) and may not trigger if the 100 * stream has already been readable from the beginning. 101 * This also implies that a stream may not be recognized as readable when data 102 * is still left in PHP's internal stream buffers. 103 * As such, it's recommended to use `stream_set_read_buffer($stream, 0);` 104 * to disable PHP's internal read buffer in this case. 105 * 106 * @param resource $stream The PHP stream resource to check. 107 * @param callable $listener Invoked when the stream is ready. 108 * @throws \Exception if the given resource type is not supported by this loop implementation 109 * @see self::removeWriteStream() 110 */ 111 public function addWriteStream($stream, $listener); 112 113 /** 114 * Remove the read event listener for the given stream. 115 * 116 * Removing a stream from the loop that has already been removed or trying 117 * to remove a stream that was never added or is invalid has no effect. 118 * 119 * @param resource $stream The PHP stream resource. 120 */ 121 public function removeReadStream($stream); 122 123 /** 124 * Remove the write event listener for the given stream. 125 * 126 * Removing a stream from the loop that has already been removed or trying 127 * to remove a stream that was never added or is invalid has no effect. 128 * 129 * @param resource $stream The PHP stream resource. 130 */ 131 public function removeWriteStream($stream); 132 133 /** 134 * Enqueue a callback to be invoked once after the given interval. 135 * 136 * The timer callback function MUST be able to accept a single parameter, 137 * the timer instance as also returned by this method or you MAY use a 138 * function which has no parameters at all. 139 * 140 * The timer callback function MUST NOT throw an `Exception`. 141 * The return value of the timer callback function will be ignored and has 142 * no effect, so for performance reasons you're recommended to not return 143 * any excessive data structures. 144 * 145 * Unlike [`addPeriodicTimer()`](#addperiodictimer), this method will ensure 146 * the callback will be invoked only once after the given interval. 147 * You can invoke [`cancelTimer`](#canceltimer) to cancel a pending timer. 148 * 149 * ```php 150 * $loop->addTimer(0.8, function () { 151 * echo 'world!' . PHP_EOL; 152 * }); 153 * 154 * $loop->addTimer(0.3, function () { 155 * echo 'hello '; 156 * }); 157 * ``` 158 * 159 * See also [example #1](examples). 160 * 161 * If you want to access any variables within your callback function, you 162 * can bind arbitrary data to a callback closure like this: 163 * 164 * ```php 165 * function hello($name, LoopInterface $loop) 166 * { 167 * $loop->addTimer(1.0, function () use ($name) { 168 * echo "hello $name\n"; 169 * }); 170 * } 171 * 172 * hello('Tester', $loop); 173 * ``` 174 * 175 * This interface does not enforce any particular timer resolution, so 176 * special care may have to be taken if you rely on very high precision with 177 * millisecond accuracy or below. Event loop implementations SHOULD work on 178 * a best effort basis and SHOULD provide at least millisecond accuracy 179 * unless otherwise noted. Many existing event loop implementations are 180 * known to provide microsecond accuracy, but it's generally not recommended 181 * to rely on this high precision. 182 * 183 * Similarly, the execution order of timers scheduled to execute at the 184 * same time (within its possible accuracy) is not guaranteed. 185 * 186 * This interface suggests that event loop implementations SHOULD use a 187 * monotonic time source if available. Given that a monotonic time source is 188 * only available as of PHP 7.3 by default, event loop implementations MAY 189 * fall back to using wall-clock time. 190 * While this does not affect many common use cases, this is an important 191 * distinction for programs that rely on a high time precision or on systems 192 * that are subject to discontinuous time adjustments (time jumps). 193 * This means that if you schedule a timer to trigger in 30s and then adjust 194 * your system time forward by 20s, the timer SHOULD still trigger in 30s. 195 * See also [event loop implementations](#loop-implementations) for more details. 196 * 197 * @param int|float $interval The number of seconds to wait before execution. 198 * @param callable $callback The callback to invoke. 199 * 200 * @return TimerInterface 201 */ 202 public function addTimer($interval, $callback); 203 204 /** 205 * Enqueue a callback to be invoked repeatedly after the given interval. 206 * 207 * The timer callback function MUST be able to accept a single parameter, 208 * the timer instance as also returned by this method or you MAY use a 209 * function which has no parameters at all. 210 * 211 * The timer callback function MUST NOT throw an `Exception`. 212 * The return value of the timer callback function will be ignored and has 213 * no effect, so for performance reasons you're recommended to not return 214 * any excessive data structures. 215 * 216 * Unlike [`addTimer()`](#addtimer), this method will ensure the the 217 * callback will be invoked infinitely after the given interval or until you 218 * invoke [`cancelTimer`](#canceltimer). 219 * 220 * ```php 221 * $timer = $loop->addPeriodicTimer(0.1, function () { 222 * echo 'tick!' . PHP_EOL; 223 * }); 224 * 225 * $loop->addTimer(1.0, function () use ($loop, $timer) { 226 * $loop->cancelTimer($timer); 227 * echo 'Done' . PHP_EOL; 228 * }); 229 * ``` 230 * 231 * See also [example #2](examples). 232 * 233 * If you want to limit the number of executions, you can bind 234 * arbitrary data to a callback closure like this: 235 * 236 * ```php 237 * function hello($name, LoopInterface $loop) 238 * { 239 * $n = 3; 240 * $loop->addPeriodicTimer(1.0, function ($timer) use ($name, $loop, &$n) { 241 * if ($n > 0) { 242 * --$n; 243 * echo "hello $name\n"; 244 * } else { 245 * $loop->cancelTimer($timer); 246 * } 247 * }); 248 * } 249 * 250 * hello('Tester', $loop); 251 * ``` 252 * 253 * This interface does not enforce any particular timer resolution, so 254 * special care may have to be taken if you rely on very high precision with 255 * millisecond accuracy or below. Event loop implementations SHOULD work on 256 * a best effort basis and SHOULD provide at least millisecond accuracy 257 * unless otherwise noted. Many existing event loop implementations are 258 * known to provide microsecond accuracy, but it's generally not recommended 259 * to rely on this high precision. 260 * 261 * Similarly, the execution order of timers scheduled to execute at the 262 * same time (within its possible accuracy) is not guaranteed. 263 * 264 * This interface suggests that event loop implementations SHOULD use a 265 * monotonic time source if available. Given that a monotonic time source is 266 * only available as of PHP 7.3 by default, event loop implementations MAY 267 * fall back to using wall-clock time. 268 * While this does not affect many common use cases, this is an important 269 * distinction for programs that rely on a high time precision or on systems 270 * that are subject to discontinuous time adjustments (time jumps). 271 * This means that if you schedule a timer to trigger in 30s and then adjust 272 * your system time forward by 20s, the timer SHOULD still trigger in 30s. 273 * See also [event loop implementations](#loop-implementations) for more details. 274 * 275 * Additionally, periodic timers may be subject to timer drift due to 276 * re-scheduling after each invocation. As such, it's generally not 277 * recommended to rely on this for high precision intervals with millisecond 278 * accuracy or below. 279 * 280 * @param int|float $interval The number of seconds to wait before execution. 281 * @param callable $callback The callback to invoke. 282 * 283 * @return TimerInterface 284 */ 285 public function addPeriodicTimer($interval, $callback); 286 287 /** 288 * Cancel a pending timer. 289 * 290 * See also [`addPeriodicTimer()`](#addperiodictimer) and [example #2](examples). 291 * 292 * Calling this method on a timer instance that has not been added to this 293 * loop instance or on a timer that has already been cancelled has no effect. 294 * 295 * @param TimerInterface $timer The timer to cancel. 296 * 297 * @return void 298 */ 299 public function cancelTimer(TimerInterface $timer); 300 301 /** 302 * Schedule a callback to be invoked on a future tick of the event loop. 303 * 304 * This works very much similar to timers with an interval of zero seconds, 305 * but does not require the overhead of scheduling a timer queue. 306 * 307 * The tick callback function MUST be able to accept zero parameters. 308 * 309 * The tick callback function MUST NOT throw an `Exception`. 310 * The return value of the tick callback function will be ignored and has 311 * no effect, so for performance reasons you're recommended to not return 312 * any excessive data structures. 313 * 314 * If you want to access any variables within your callback function, you 315 * can bind arbitrary data to a callback closure like this: 316 * 317 * ```php 318 * function hello($name, LoopInterface $loop) 319 * { 320 * $loop->futureTick(function () use ($name) { 321 * echo "hello $name\n"; 322 * }); 323 * } 324 * 325 * hello('Tester', $loop); 326 * ``` 327 * 328 * Unlike timers, tick callbacks are guaranteed to be executed in the order 329 * they are enqueued. 330 * Also, once a callback is enqueued, there's no way to cancel this operation. 331 * 332 * This is often used to break down bigger tasks into smaller steps (a form 333 * of cooperative multitasking). 334 * 335 * ```php 336 * $loop->futureTick(function () { 337 * echo 'b'; 338 * }); 339 * $loop->futureTick(function () { 340 * echo 'c'; 341 * }); 342 * echo 'a'; 343 * ``` 344 * 345 * See also [example #3](examples). 346 * 347 * @param callable $listener The callback to invoke. 348 * 349 * @return void 350 */ 351 public function futureTick($listener); 352 353 /** 354 * Register a listener to be notified when a signal has been caught by this process. 355 * 356 * This is useful to catch user interrupt signals or shutdown signals from 357 * tools like `supervisor` or `systemd`. 358 * 359 * The listener callback function MUST be able to accept a single parameter, 360 * the signal added by this method or you MAY use a function which 361 * has no parameters at all. 362 * 363 * The listener callback function MUST NOT throw an `Exception`. 364 * The return value of the listener callback function will be ignored and has 365 * no effect, so for performance reasons you're recommended to not return 366 * any excessive data structures. 367 * 368 * ```php 369 * $loop->addSignal(SIGINT, function (int $signal) { 370 * echo 'Caught user interrupt signal' . PHP_EOL; 371 * }); 372 * ``` 373 * 374 * See also [example #4](examples). 375 * 376 * Signaling is only available on Unix-like platform, Windows isn't 377 * supported due to operating system limitations. 378 * This method may throw a `BadMethodCallException` if signals aren't 379 * supported on this platform, for example when required extensions are 380 * missing. 381 * 382 * **Note: A listener can only be added once to the same signal, any 383 * attempts to add it more then once will be ignored.** 384 * 385 * @param int $signal 386 * @param callable $listener 387 * 388 * @throws \BadMethodCallException when signals aren't supported on this 389 * platform, for example when required extensions are missing. 390 * 391 * @return void 392 */ 393 public function addSignal($signal, $listener); 394 395 /** 396 * Removes a previously added signal listener. 397 * 398 * ```php 399 * $loop->removeSignal(SIGINT, $listener); 400 * ``` 401 * 402 * Any attempts to remove listeners that aren't registered will be ignored. 403 * 404 * @param int $signal 405 * @param callable $listener 406 * 407 * @return void 408 */ 409 public function removeSignal($signal, $listener); 410 411 /** 412 * Run the event loop until there are no more tasks to perform. 413 * 414 * For many applications, this method is the only directly visible 415 * invocation on the event loop. 416 * As a rule of thumb, it is usally recommended to attach everything to the 417 * same loop instance and then run the loop once at the bottom end of the 418 * application. 419 * 420 * ```php 421 * $loop->run(); 422 * ``` 423 * 424 * This method will keep the loop running until there are no more tasks 425 * to perform. In other words: This method will block until the last 426 * timer, stream and/or signal has been removed. 427 * 428 * Likewise, it is imperative to ensure the application actually invokes 429 * this method once. Adding listeners to the loop and missing to actually 430 * run it will result in the application exiting without actually waiting 431 * for any of the attached listeners. 432 * 433 * This method MUST NOT be called while the loop is already running. 434 * This method MAY be called more than once after it has explicity been 435 * [`stop()`ped](#stop) or after it automatically stopped because it 436 * previously did no longer have anything to do. 437 * 438 * @return void 439 */ 440 public function run(); 441 442 /** 443 * Instruct a running event loop to stop. 444 * 445 * This method is considered advanced usage and should be used with care. 446 * As a rule of thumb, it is usually recommended to let the loop stop 447 * only automatically when it no longer has anything to do. 448 * 449 * This method can be used to explicitly instruct the event loop to stop: 450 * 451 * ```php 452 * $loop->addTimer(3.0, function () use ($loop) { 453 * $loop->stop(); 454 * }); 455 * ``` 456 * 457 * Calling this method on a loop instance that is not currently running or 458 * on a loop instance that has already been stopped has no effect. 459 * 460 * @return void 461 */ 462 public function stop(); 463} 464