diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:38:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:38:42 +0000 |
commit | c3ca98e1b35123f226c7f4c596b5dee78caa4223 (patch) | |
tree | 9b6eb109283da55e7d9064baa9fac795a40264cb /vendor/clue/block-react/src | |
parent | Initial commit. (diff) | |
download | icinga-php-thirdparty-upstream.tar.xz icinga-php-thirdparty-upstream.zip |
Adding upstream version 0.11.0.upstream/0.11.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/clue/block-react/src')
-rw-r--r-- | vendor/clue/block-react/src/functions.php | 357 | ||||
-rw-r--r-- | vendor/clue/block-react/src/functions_include.php | 8 |
2 files changed, 365 insertions, 0 deletions
diff --git a/vendor/clue/block-react/src/functions.php b/vendor/clue/block-react/src/functions.php new file mode 100644 index 0000000..6afe2e0 --- /dev/null +++ b/vendor/clue/block-react/src/functions.php @@ -0,0 +1,357 @@ +<?php + +namespace Clue\React\Block; + +use React\EventLoop\Loop; +use React\EventLoop\LoopInterface; +use React\Promise; +use React\Promise\CancellablePromiseInterface; +use React\Promise\PromiseInterface; +use React\Promise\Timer; +use React\Promise\Timer\TimeoutException; +use Exception; +use UnderflowException; + +/** + * Wait/sleep for `$time` seconds. + * + * ```php + * Clue\React\Block\sleep(1.5, $loop); + * ``` + * + * This function will only return after the given `$time` has elapsed. In the + * meantime, the event loop will run any other events attached to the same loop + * until the timer fires. If there are no other events attached to this loop, + * it will behave similar to the built-in [`sleep()`](https://www.php.net/manual/en/function.sleep.php). + * + * Internally, the `$time` argument will be used as a timer for the loop so that + * it keeps running until this timer triggers. This implies that if you pass a + * really small (or negative) value, it will still start a timer and will thus + * trigger at the earliest possible time in the future. + * + * This function takes an optional `LoopInterface|null $loop` parameter that can be used to + * pass the event loop instance to use. You can use a `null` value here in order to + * use the [default loop](https://github.com/reactphp/event-loop#loop). This value + * SHOULD NOT be given unless you're sure you want to explicitly use a given event + * loop instance. + * + * Note that this function will assume control over the event loop. Internally, it + * will actually `run()` the loop until the timer fires and then calls `stop()` to + * terminate execution of the loop. This means this function is more suited for + * short-lived program executions when using async APIs is not feasible. For + * long-running applications, using event-driven APIs by leveraging timers + * is usually preferable. + * + * @param float $time + * @param ?LoopInterface $loop + * @return void + */ +function sleep($time, LoopInterface $loop = null) +{ + await(Timer\resolve($time, $loop), $loop); +} + +/** + * Block waiting for the given `$promise` to be fulfilled. + * + * ```php + * $result = Clue\React\Block\await($promise, $loop); + * ``` + * + * This function will only return after the given `$promise` has settled, i.e. + * either fulfilled or rejected. In the meantime, the event loop will run any + * events attached to the same loop until the promise settles. + * + * Once the promise is fulfilled, this function will return whatever the promise + * resolved to. + * + * Once the promise is rejected, this will throw whatever the promise rejected + * with. If the promise did not reject with an `Exception`, then this function + * will throw an `UnexpectedValueException` instead. + * + * ```php + * try { + * $result = Clue\React\Block\await($promise, $loop); + * // promise successfully fulfilled with $result + * echo 'Result: ' . $result; + * } catch (Exception $exception) { + * // promise rejected with $exception + * echo 'ERROR: ' . $exception->getMessage(); + * } + * ``` + * + * See also the [examples](../examples/). + * + * This function takes an optional `LoopInterface|null $loop` parameter that can be used to + * pass the event loop instance to use. You can use a `null` value here in order to + * use the [default loop](https://github.com/reactphp/event-loop#loop). This value + * SHOULD NOT be given unless you're sure you want to explicitly use a given event + * loop instance. + * + * If no `$timeout` argument is given and the promise stays pending, then this + * will potentially wait/block forever until the promise is settled. To avoid + * this, API authors creating promises are expected to provide means to + * configure a timeout for the promise instead. For more details, see also the + * [`timeout()` function](https://github.com/reactphp/promise-timer#timeout). + * + * If the deprecated `$timeout` argument is given and the promise is still pending once the + * timeout triggers, this will `cancel()` the promise and throw a `TimeoutException`. + * This implies that if you pass a really small (or negative) value, it will still + * start a timer and will thus trigger at the earliest possible time in the future. + * + * Note that this function will assume control over the event loop. Internally, it + * will actually `run()` the loop until the promise settles and then calls `stop()` to + * terminate execution of the loop. This means this function is more suited for + * short-lived promise executions when using promise-based APIs is not feasible. + * For long-running applications, using promise-based APIs by leveraging chained + * `then()` calls is usually preferable. + * + * @param PromiseInterface $promise + * @param ?LoopInterface $loop + * @param ?float $timeout [deprecated] (optional) maximum timeout in seconds or null=wait forever + * @return mixed returns whatever the promise resolves to + * @throws Exception when the promise is rejected + * @throws TimeoutException if the $timeout is given and triggers + */ +function await(PromiseInterface $promise, LoopInterface $loop = null, $timeout = null) +{ + $wait = true; + $resolved = null; + $exception = null; + $rejected = false; + $loop = $loop ?: Loop::get(); + + if ($timeout !== null) { + $promise = Timer\timeout($promise, $timeout, $loop); + } + + $promise->then( + function ($c) use (&$resolved, &$wait, $loop) { + $resolved = $c; + $wait = false; + $loop->stop(); + }, + function ($error) use (&$exception, &$rejected, &$wait, $loop) { + $exception = $error; + $rejected = true; + $wait = false; + $loop->stop(); + } + ); + + // Explicitly overwrite argument with null value. This ensure that this + // argument does not show up in the stack trace in PHP 7+ only. + $promise = null; + + while ($wait) { + $loop->run(); + } + + if ($rejected) { + if (!$exception instanceof \Exception && !$exception instanceof \Throwable) { + $exception = new \UnexpectedValueException( + 'Promise rejected with unexpected value of type ' . (is_object($exception) ? get_class($exception) : gettype($exception)) + ); + } elseif (!$exception instanceof \Exception) { + $exception = new \UnexpectedValueException( + 'Promise rejected with unexpected ' . get_class($exception) . ': ' . $exception->getMessage(), + $exception->getCode(), + $exception + ); + } + + throw $exception; + } + + return $resolved; +} + +/** + * Wait for ANY of the given promises to be fulfilled. + * + * ```php + * $promises = array( + * $promise1, + * $promise2 + * ); + * + * $firstResult = Clue\React\Block\awaitAny($promises, $loop); + * + * echo 'First result: ' . $firstResult; + * ``` + * + * See also the [examples](../examples/). + * + * This function will only return after ANY of the given `$promises` has been + * fulfilled or will throw when ALL of them have been rejected. In the meantime, + * the event loop will run any events attached to the same loop. + * + * Once ANY promise is fulfilled, this function will return whatever this + * promise resolved to and will try to `cancel()` all remaining promises. + * + * Once ALL promises reject, this function will fail and throw an `UnderflowException`. + * Likewise, this will throw if an empty array of `$promises` is passed. + * + * This function takes an optional `LoopInterface|null $loop` parameter that can be used to + * pass the event loop instance to use. You can use a `null` value here in order to + * use the [default loop](https://github.com/reactphp/event-loop#loop). This value + * SHOULD NOT be given unless you're sure you want to explicitly use a given event + * loop instance. + * + * If no `$timeout` argument is given and ALL promises stay pending, then this + * will potentially wait/block forever until the promise is fulfilled. To avoid + * this, API authors creating promises are expected to provide means to + * configure a timeout for the promise instead. For more details, see also the + * [`timeout()` function](https://github.com/reactphp/promise-timer#timeout). + * + * If the deprecated `$timeout` argument is given and ANY promises are still pending once + * the timeout triggers, this will `cancel()` all pending promises and throw a + * `TimeoutException`. This implies that if you pass a really small (or negative) + * value, it will still start a timer and will thus trigger at the earliest + * possible time in the future. + * + * Note that this function will assume control over the event loop. Internally, it + * will actually `run()` the loop until the promise settles and then calls `stop()` to + * terminate execution of the loop. This means this function is more suited for + * short-lived promise executions when using promise-based APIs is not feasible. + * For long-running applications, using promise-based APIs by leveraging chained + * `then()` calls is usually preferable. + * + * @param PromiseInterface[] $promises + * @param ?LoopInterface $loop + * @param ?float $timeout [deprecated] (optional) maximum timeout in seconds or null=wait forever + * @return mixed returns whatever the first promise resolves to + * @throws Exception if ALL promises are rejected + * @throws TimeoutException if the $timeout is given and triggers + */ +function awaitAny(array $promises, LoopInterface $loop = null, $timeout = null) +{ + // Explicitly overwrite argument with null value. This ensure that this + // argument does not show up in the stack trace in PHP 7+ only. + $all = $promises; + $promises = null; + + try { + // Promise\any() does not cope with an empty input array, so reject this here + if (!$all) { + throw new UnderflowException('Empty input array'); + } + + $ret = await(Promise\any($all)->then(null, function () { + // rejects with an array of rejection reasons => reject with Exception instead + throw new Exception('All promises rejected'); + }), $loop, $timeout); + } catch (TimeoutException $e) { + // the timeout fired + // => try to cancel all promises (rejected ones will be ignored anyway) + _cancelAllPromises($all); + + throw $e; + } catch (Exception $e) { + // if the above throws, then ALL promises are already rejected + // => try to cancel all promises (rejected ones will be ignored anyway) + _cancelAllPromises($all); + + throw new UnderflowException('No promise could resolve', 0, $e); + } + + // if we reach this, then ANY of the given promises resolved + // => try to cancel all promises (settled ones will be ignored anyway) + _cancelAllPromises($all); + + return $ret; +} + +/** + * Wait for ALL of the given promises to be fulfilled. + * + * ```php + * $promises = array( + * $promise1, + * $promise2 + * ); + * + * $allResults = Clue\React\Block\awaitAll($promises, $loop); + * + * echo 'First promise resolved with: ' . $allResults[0]; + * ``` + * + * See also the [examples](../examples/). + * + * This function will only return after ALL of the given `$promises` have been + * fulfilled or will throw when ANY of them have been rejected. In the meantime, + * the event loop will run any events attached to the same loop. + * + * Once ALL promises are fulfilled, this will return an array with whatever + * each promise resolves to. Array keys will be left intact, i.e. they can + * be used to correlate the return array to the promises passed. + * + * Once ANY promise rejects, this will try to `cancel()` all remaining promises + * and throw an `Exception`. If the promise did not reject with an `Exception`, + * then this function will throw an `UnexpectedValueException` instead. + * + * This function takes an optional `LoopInterface|null $loop` parameter that can be used to + * pass the event loop instance to use. You can use a `null` value here in order to + * use the [default loop](https://github.com/reactphp/event-loop#loop). This value + * SHOULD NOT be given unless you're sure you want to explicitly use a given event + * loop instance. + * + * If no `$timeout` argument is given and ANY promises stay pending, then this + * will potentially wait/block forever until the promise is fulfilled. To avoid + * this, API authors creating promises are expected to provide means to + * configure a timeout for the promise instead. For more details, see also the + * [`timeout()` function](https://github.com/reactphp/promise-timer#timeout). + * + * If the deprecated `$timeout` argument is given and ANY promises are still pending once + * the timeout triggers, this will `cancel()` all pending promises and throw a + * `TimeoutException`. This implies that if you pass a really small (or negative) + * value, it will still start a timer and will thus trigger at the earliest + * possible time in the future. + * + * Note that this function will assume control over the event loop. Internally, it + * will actually `run()` the loop until the promise settles and then calls `stop()` to + * terminate execution of the loop. This means this function is more suited for + * short-lived promise executions when using promise-based APIs is not feasible. + * For long-running applications, using promise-based APIs by leveraging chained + * `then()` calls is usually preferable. + * + * @param PromiseInterface[] $promises + * @param ?LoopInterface $loop + * @param ?float $timeout [deprecated] (optional) maximum timeout in seconds or null=wait forever + * @return array returns an array with whatever each promise resolves to + * @throws Exception when ANY promise is rejected + * @throws TimeoutException if the $timeout is given and triggers + */ +function awaitAll(array $promises, LoopInterface $loop = null, $timeout = null) +{ + // Explicitly overwrite argument with null value. This ensure that this + // argument does not show up in the stack trace in PHP 7+ only. + $all = $promises; + $promises = null; + + try { + return await(Promise\all($all), $loop, $timeout); + } catch (Exception $e) { + // ANY of the given promises rejected or the timeout fired + // => try to cancel all promises (rejected ones will be ignored anyway) + _cancelAllPromises($all); + + throw $e; + } +} + +/** + * internal helper function used to iterate over an array of Promise instances and cancel() each + * + * @internal + * @param array $promises + * @return void + */ +function _cancelAllPromises(array $promises) +{ + foreach ($promises as $promise) { + if ($promise instanceof PromiseInterface && ($promise instanceof CancellablePromiseInterface || !\interface_exists('React\Promise\CancellablePromiseInterface'))) { + $promise->cancel(); + } + } +} diff --git a/vendor/clue/block-react/src/functions_include.php b/vendor/clue/block-react/src/functions_include.php new file mode 100644 index 0000000..b3ad74c --- /dev/null +++ b/vendor/clue/block-react/src/functions_include.php @@ -0,0 +1,8 @@ +<?php + +namespace Clue\React\Block; + +if (!function_exists('Clue\\React\\Block\\sleep')) { + require __DIR__ . '/functions.php'; +} + |