Method
phasync::run
Runs $fn and returns its result once it and every coroutine started inside it have ended.
Description#
public static phasync::run(
callable $fn,
mixed ...$args
): mixedOutside a coroutine, run() starts the event loop, runs $fn as a coroutine and blocks the process until then. This is how a script, a test or a controller under PHP-FPM enters phasync. Inside a coroutine it runs $fn in that coroutine, in a new frame: the calling coroutine waits for what $fn started, and the others go on. A nested run() costs no coroutine, so a server can give each request one.
Every run() creates a Frame: the coroutines started inside it belong to it, also those started by its coroutines, and it waits for them. A failure does not cancel the others. Once they have all ended, run() throws every failure: what $fn threw and each failure of a coroutine nobody awaited (a later await counts, until run() ends). One is thrown as it is; several in an AggregateException, $fn's first, then by the time they happened. Without failures it returns what $fn returned. A coroutine that ends with a cancellation phasync issued is no failure. With an exception handler on the frame (Frame::setExceptionHandler), the failures nobody awaited go to it instead. When coroutines wait and nothing can ever wake them, the outermost run() cancels its coroutines and throws a DeadlockException.
When the outermost run() has no coroutine left, it cancels the services (phasync::service) and returns once they have ended. run() does not change the current Scope: $fn runs in the caller's.
Parameters#
- $fn callable
- What to run
- ...$args mixed
- Passed to
$fn
Return values#
What $fn returned mixed
Errors / Exceptions#
| Exception | When |
|---|---|
Throwable | What $fn threw, or the failure of a coroutine nobody awaited, when there is one |
AggregateException | When there are several |
TimeoutException | When the frame's deadline passed (Frame::setTimeout) |
DeadlockException | From the outermost run(), when coroutines wait and nothing can wake them |
LogicException | Inside the event loop but outside a coroutine (an onScopeChange() hook) |
Examples#
$result = phasync::run(function () {
phasync::go(function () {
phasync::sleep(0.1);
echo "second\n";
});
echo "first\n";
return 'done';
});
echo "third: $result\n"; // run() returned after the coroutine endedSee also#
phasync::goStarts a coroutine without waiting for itphasync::frameReturns the frame of the running coroutine: that of the innermostrun()it is in.phasync::awaitWaits for a coroutine or a promise, and returns its result or throws the exception it ended with.phasync::serviceStarts$fnas a service: a coroutine of no frame, in the root scope, which outlives the code that started it, and returns it.DeadlockExceptionCoroutines wait, and nothing can ever wake them: the outermostrun()throws this.