From c3ca98e1b35123f226c7f4c596b5dee78caa4223 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 14:38:42 +0200 Subject: Adding upstream version 0.11.0. Signed-off-by: Daniel Baumann --- .../react/promise-timer/src/TimeoutException.php | 35 +++ vendor/react/promise-timer/src/functions.php | 330 +++++++++++++++++++++ .../react/promise-timer/src/functions_include.php | 7 + 3 files changed, 372 insertions(+) create mode 100644 vendor/react/promise-timer/src/TimeoutException.php create mode 100644 vendor/react/promise-timer/src/functions.php create mode 100644 vendor/react/promise-timer/src/functions_include.php (limited to 'vendor/react/promise-timer/src') diff --git a/vendor/react/promise-timer/src/TimeoutException.php b/vendor/react/promise-timer/src/TimeoutException.php new file mode 100644 index 0000000..7f03ba0 --- /dev/null +++ b/vendor/react/promise-timer/src/TimeoutException.php @@ -0,0 +1,35 @@ +timeout = (float) $timeout; + } + + /** + * Get the timeout value in seconds. + * + * @return float + */ + public function getTimeout() + { + return $this->timeout; + } +} diff --git a/vendor/react/promise-timer/src/functions.php b/vendor/react/promise-timer/src/functions.php new file mode 100644 index 0000000..b72bf36 --- /dev/null +++ b/vendor/react/promise-timer/src/functions.php @@ -0,0 +1,330 @@ +then(function ($value) { + * // the operation finished within 10.0 seconds + * }); + * ``` + * + * A more complete example could look like this: + * + * ```php + * $promise = accessSomeRemoteResource(); + * React\Promise\Timer\timeout($promise, 10.0)->then( + * function ($value) { + * // the operation finished within 10.0 seconds + * }, + * function ($error) { + * if ($error instanceof React\Promise\Timer\TimeoutException) { + * // the operation has failed due to a timeout + * } else { + * // the input operation has failed due to some other error + * } + * } + * ); + * ``` + * + * Or if you're using [react/promise v3](https://github.com/reactphp/promise): + * + * ```php + * React\Promise\Timer\timeout($promise, 10.0)->then(function ($value) { + * // the operation finished within 10.0 seconds + * })->catch(function (React\Promise\Timer\TimeoutException $error) { + * // the operation has failed due to a timeout + * })->catch(function (Throwable $error) { + * // the input operation has failed due to some other error + * }); + * ``` + * + * As discussed above, the [`timeout()`](#timeout) function will take care of + * the underlying operation if it takes *too long*. In this case, you can be + * sure the resulting promise will always be rejected with a + * [`TimeoutException`](#timeoutexception). On top of this, the function will + * try to *cancel* the underlying operation. Responsibility for this + * cancellation logic is left up to the underlying operation. + * + * - A common use case involves cleaning up any resources like open network + * sockets or file handles or terminating external processes or timers. + * + * - If the given input `$promise` does not support cancellation, then this is a + * NO-OP. This means that while the resulting promise will still be rejected, + * the underlying input `$promise` may still be pending and can hence continue + * consuming resources + * + * On top of this, the returned promise is implemented in such a way that it can + * be cancelled when it is still pending. Cancelling a pending promise will + * cancel the underlying operation. As discussed above, responsibility for this + * cancellation logic is left up to the underlying operation. + * + * ```php + * $promise = accessSomeRemoteResource(); + * $timeout = React\Promise\Timer\timeout($promise, 10.0); + * + * $timeout->cancel(); + * ``` + * + * For more details on the promise cancellation, please refer to the + * [Promise documentation](https://github.com/reactphp/promise#cancellablepromiseinterface). + * + * If you want to wait for multiple promises to resolve, you can use the normal + * promise primitives like this: + * + * ```php + * $promises = array( + * accessSomeRemoteResource(), + * accessSomeRemoteResource(), + * accessSomeRemoteResource() + * ); + * + * $promise = React\Promise\all($promises); + * + * React\Promise\Timer\timeout($promise, 10)->then(function ($values) { + * // *all* promises resolved + * }); + * ``` + * + * The applies to all promise collection primitives alike, i.e. `all()`, + * `race()`, `any()`, `some()` etc. + * + * For more details on the promise primitives, please refer to the + * [Promise documentation](https://github.com/reactphp/promise#functions). + * + * @param PromiseInterface $promise + * @param float $time + * @param ?LoopInterface $loop + * @return PromiseInterface + */ +function timeout(PromiseInterface $promise, $time, LoopInterface $loop = null) +{ + // cancelling this promise will only try to cancel the input promise, + // thus leaving responsibility to the input promise. + $canceller = null; + if (\method_exists($promise, 'cancel')) { + // pass promise by reference to clean reference after cancellation handler + // has been invoked once in order to avoid garbage references in call stack. + $canceller = function () use (&$promise) { + $promise->cancel(); + $promise = null; + }; + } + + if ($loop === null) { + $loop = Loop::get(); + } + + return new Promise(function ($resolve, $reject) use ($loop, $time, $promise) { + $timer = null; + $promise = $promise->then(function ($v) use (&$timer, $loop, $resolve) { + if ($timer) { + $loop->cancelTimer($timer); + } + $timer = false; + $resolve($v); + }, function ($v) use (&$timer, $loop, $reject) { + if ($timer) { + $loop->cancelTimer($timer); + } + $timer = false; + $reject($v); + }); + + // promise already resolved => no need to start timer + if ($timer === false) { + return; + } + + // start timeout timer which will cancel the input promise + $timer = $loop->addTimer($time, function () use ($time, &$promise, $reject) { + $reject(new TimeoutException($time, 'Timed out after ' . $time . ' seconds')); + + // try to invoke cancellation handler of input promise and then clean + // reference in order to avoid garbage references in call stack. + if (\method_exists($promise, 'cancel')) { + $promise->cancel(); + } + $promise = null; + }); + }, $canceller); +} + +/** + * Create a new promise that resolves in `$time` seconds. + * + * ```php + * React\Promise\Timer\sleep(1.5)->then(function () { + * echo 'Thanks for waiting!' . PHP_EOL; + * }); + * ``` + * + * Internally, the given `$time` value will be used to start a timer that will + * resolve the promise once it 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. + * + * The returned promise is implemented in such a way that it can be cancelled + * when it is still pending. Cancelling a pending promise will reject its value + * with a `RuntimeException` and clean up any pending timers. + * + * ```php + * $timer = React\Promise\Timer\sleep(2.0); + * + * $timer->cancel(); + * ``` + * + * @param float $time + * @param ?LoopInterface $loop + * @return PromiseInterface + */ +function sleep($time, LoopInterface $loop = null) +{ + if ($loop === null) { + $loop = Loop::get(); + } + + $timer = null; + return new Promise(function ($resolve) use ($loop, $time, &$timer) { + // resolve the promise when the timer fires in $time seconds + $timer = $loop->addTimer($time, function () use ($resolve) { + $resolve(null); + }); + }, function () use (&$timer, $loop) { + // cancelling this promise will cancel the timer, clean the reference + // in order to avoid garbage references in call stack and then reject. + $loop->cancelTimer($timer); + $timer = null; + + throw new \RuntimeException('Timer cancelled'); + }); +} + +/** + * [Deprecated] Create a new promise that resolves in `$time` seconds with the `$time` as the fulfillment value. + * + * ```php + * React\Promise\Timer\resolve(1.5)->then(function ($time) { + * echo 'Thanks for waiting ' . $time . ' seconds' . PHP_EOL; + * }); + * ``` + * + * Internally, the given `$time` value will be used to start a timer that will + * resolve the promise once it 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. + * + * The returned promise is implemented in such a way that it can be cancelled + * when it is still pending. Cancelling a pending promise will reject its value + * with a `RuntimeException` and clean up any pending timers. + * + * ```php + * $timer = React\Promise\Timer\resolve(2.0); + * + * $timer->cancel(); + * ``` + * + * @param float $time + * @param ?LoopInterface $loop + * @return PromiseInterface + * @deprecated 1.8.0 See `sleep()` instead + * @see sleep() + */ +function resolve($time, LoopInterface $loop = null) +{ + return sleep($time, $loop)->then(function() use ($time) { + return $time; + }); +} + +/** + * [Deprecated] Create a new promise which rejects in `$time` seconds with a `TimeoutException`. + * + * ```php + * React\Promise\Timer\reject(2.0)->then(null, function (React\Promise\Timer\TimeoutException $e) { + * echo 'Rejected after ' . $e->getTimeout() . ' seconds ' . PHP_EOL; + * }); + * ``` + * + * Internally, the given `$time` value will be used to start a timer that will + * reject the promise once it 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. + * + * The returned promise is implemented in such a way that it can be cancelled + * when it is still pending. Cancelling a pending promise will reject its value + * with a `RuntimeException` and clean up any pending timers. + * + * ```php + * $timer = React\Promise\Timer\reject(2.0); + * + * $timer->cancel(); + * ``` + * + * @param float $time + * @param LoopInterface $loop + * @return PromiseInterface + * @deprecated 1.8.0 See `sleep()` instead + * @see sleep() + */ +function reject($time, LoopInterface $loop = null) +{ + return sleep($time, $loop)->then(function () use ($time) { + throw new TimeoutException($time, 'Timer expired after ' . $time . ' seconds'); + }); +} diff --git a/vendor/react/promise-timer/src/functions_include.php b/vendor/react/promise-timer/src/functions_include.php new file mode 100644 index 0000000..1d5673a --- /dev/null +++ b/vendor/react/promise-timer/src/functions_include.php @@ -0,0 +1,7 @@ +