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