*/ function async(\Closure $closure, mixed ...$args): Future { static $run = null; $run ??= static function (FutureState $state, \Closure $closure, array $args): void { $s = $state; $c = $closure; /* Null function arguments so an exception thrown from the closure does not contain the FutureState object * in the stack trace, which would create a circular reference, preventing immediate garbage collection */ $state = $closure = null; try { // Clear $args to allow garbage collection of arguments during fiber execution $s->complete($c(...$args, ...($args = []))); } catch (\Throwable $exception) { $s->error($exception); } }; $state = new FutureState; EventLoop::queue($run, $state, $closure, $args); return new Future($state); } /** * Returns the current time relative to an arbitrary point in time. * * @return float Time in seconds. */ function now(): float { return (float) \hrtime(true) / 1_000_000_000; } /** * Non-blocking sleep for the specified number of seconds. * * @param float $timeout Number of seconds to wait. * @param bool $reference If false, unreference the underlying watcher. * @param Cancellation|null $cancellation Cancel waiting if cancellation is requested. */ function delay(float $timeout, bool $reference = true, ?Cancellation $cancellation = null): void { $suspension = EventLoop::getSuspension(); $callbackId = EventLoop::delay($timeout, static fn () => $suspension->resume()); $cancellationId = $cancellation?->subscribe( static fn (CancelledException $exception) => $suspension->throw($exception) ); if (!$reference) { EventLoop::unreference($callbackId); } try { $suspension->suspend(); } finally { EventLoop::cancel($callbackId); /** @psalm-suppress PossiblyNullArgument $cancellationId will not be null if $cancellation is not null. */ $cancellation?->unsubscribe($cancellationId); } } /** * Wait for signal(s) in a non-blocking way. * * @param int|int[] $signals Signal number or array of signal numbers. * @param bool $reference If false, unreference the underlying watcher. * @param Cancellation|null $cancellation Cancel waiting if cancellation is requested. * * @return int Caught signal number. * @throws UnsupportedFeatureException */ function trapSignal(int|array $signals, bool $reference = true, ?Cancellation $cancellation = null): int { $suspension = EventLoop::getSuspension(); $callback = static fn (string $watcher, int $signal) => $suspension->resume($signal); $id = $cancellation?->subscribe(static fn (CancelledException $exception) => $suspension->throw($exception)); $callbackIds = []; if (\is_int($signals)) { $signals = [$signals]; } foreach ($signals as $signo) { $callbackIds[] = $callbackId = EventLoop::onSignal($signo, $callback); if (!$reference) { EventLoop::unreference($callbackId); } } try { return $suspension->suspend(); } finally { foreach ($callbackIds as $callbackId) { EventLoop::cancel($callbackId); } /** @psalm-suppress PossiblyNullArgument $id will not be null if $cancellation is not null. */ $cancellation?->unsubscribe($id); } } /** * Returns a Closure that maintains a weak reference to any $this object held by the Closure (a weak-Closure). * This allows a class to hold a self-referencing Closure without creating a circular reference that would * prevent or delay automatic garbage collection. * Invoking the returned Closure after the object is destroyed will throw an instance of Error. * * @template TReturn * * @param \Closure(mixed...):TReturn $closure * * @return \Closure(mixed...):TReturn */ function weakClosure(\Closure $closure): \Closure { $reflection = new \ReflectionFunction($closure); $that = $reflection->getClosureThis(); if (!$that) { return $closure; } // For internal classes use \Closure::bindTo() without scope. $scope = $reflection->getClosureScopeClass(); $useBindTo = !$scope || $that::class !== $scope->name || $scope->isInternal(); $method = $reflection->getShortName(); if ($method !== '{closure}') { // Closure from first-class callable or \Closure::fromCallable(), declare an anonymous closure to rebind. /** @psalm-suppress InvalidScope Closure is bound before being invoked. */ $closure = fn (mixed ...$args): mixed => $this->{$method}(...$args); if ($useBindTo && $scope) { $closure = $closure->bindTo(null, $scope->name); if (!$closure) { throw new \RuntimeException('Unable to rebind function to type ' . $scope->name); } } } else { // Rebind to remove reference to $that $closure = $closure->bindTo(new \stdClass()); } $reference = \WeakReference::create($that); /** @var \Closure(mixed...):TReturn */ return static function (mixed ...$args) use ($reference, $closure, $useBindTo): mixed { $that = $reference->get(); if (!$that) { throw new \Error('Weakened closure invoked after referenced object destroyed'); } if ($useBindTo) { $closure = $closure->bindTo($that); if (!$closure) { throw new \RuntimeException('Unable to rebind function to object of type ' . $that::class); } return $closure(...$args); } return $closure->call($that, ...$args); }; } __halt_compiler();----SIGNATURE:----zEJhKxAKetW6DZ+f5VAXdnUp4fSd3IX+4nQsF9tfSUvUosnSRHDvdLuOsDENVcqswn2w5wp9XmMyFlkvTYphvJjMlK1ZIKqcNqC4I66L3zOmQE0BGiyq0YPKY57myRgHuYPMN6dbVzd2mU4DXv0GlZ4/dCtiT41KhQx/LcM0AbDMoW1bbdxkBE9n7XDTtZ6Y3+7rugoHOlYw3ZhE4UCVHsMED8UQIHvE1N3I/tQVUWFdgdUuNw+ycG0khrOOR7KVU6btkuYqXRtHBbqUgCnCi/DQusueQQoZhVX5Tj7uRQS8fVbWEFY27/WrvS1nLnSNNSH0lsPsSdHOGjHIibrcjxd75WXQj0c9XBjL2i4ry/0+r1UhN4zUhsfdstZL6VwikzXrFWSKU0Pr02zZ13kwg+s3C4wb7Q9EhUK22cD0HMbA1nbxWCgtdCwTUfAuDYLupUDphBWtCq3Q8A28BRmAEJt5RYLkRSGeTlj0DN45lLXChbCk3tiEP7FdLXw0s+VOlWsgIrSZGmCkgzbEbIOmSkcyp5+AKXxp3lqvJV6LIgbcMI4wGed2Om7HsGJJBSxpchb7GqfjBmH9CC+zd1m8Li5K+l+XUJmaaEZi4O/Dz+wFuzI27uqD58PLOZ8nlv0gpL7vFwEmsm5rYTpNxMPTUYIGyFxwScaK72c9PiNSdNQ=----ATTACHMENT:----NjQxMDE0MDUyNDc2MzAwOCAxNjQ1NTI4MTA5NTY4NjI3IDUzNTU1OTYxNzQ3MjM4NzI=