*/ private array $callbacks = []; /** @var T|null */ private mixed $result = null; private ?\Throwable $throwable = null; private ?string $origin = null; public function __construct() { \assert((function () { if (isDebugEnabled()) { $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS); \array_shift($trace); // remove current closure $this->origin = formatStacktrace($trace); } return true; })()); } public function __destruct() { if ($this->throwable && !$this->handled) { $throwable = new UnhandledFutureError($this->throwable, $this->origin); EventLoop::queue(static fn () => throw $throwable); } } /** * Registers a callback to be notified once the operation is complete or errored. * * The callback is invoked directly from the event loop context, so suspension within the callback is not possible. * * @param \Closure(?\Throwable, ?T, string): void $callback Callback invoked on error / successful completion of * the future. * * @return string Identifier that can be used to cancel interest for this future. */ public function subscribe(\Closure $callback): string { $id = self::$nextId++; $this->handled = true; // Even if unsubscribed later, consider the future handled. if ($this->complete) { EventLoop::queue($callback, $this->throwable, $this->result, $id); } else { $this->callbacks[$id] = $callback; } return $id; } /** * Cancels a subscription. * * Cancellations are advisory only. The callback might still be called if it is already queued for execution. * * @param string $id Identifier returned from subscribe() */ public function unsubscribe(string $id): void { unset($this->callbacks[$id]); } /** * Completes the operation with a result value. * * @param T $result Result of the operation. */ public function complete(mixed $result): void { if ($this->complete) { throw new \Error('Operation is no longer pending'); } if ($result instanceof Future) { throw new \Error('Cannot complete with an instance of ' . Future::class); } $this->result = $result; $this->invokeCallbacks(); } /** * Marks the operation as failed. * * @param \Throwable $throwable Throwable to indicate the error. */ public function error(\Throwable $throwable): void { if ($this->complete) { throw new \Error('Operation is no longer pending'); } $this->throwable = $throwable; $this->invokeCallbacks(); } /** * @return bool True if the operation has completed. */ public function isComplete(): bool { return $this->complete; } /** * Suppress the exception thrown to the loop error handler if and operation error is not handled by a callback. */ public function ignore(): void { $this->handled = true; } private function invokeCallbacks(): void { $this->complete = true; foreach ($this->callbacks as $id => $callback) { EventLoop::queue($callback, $this->throwable, $this->result, $id); } $this->callbacks = []; } } __halt_compiler();----SIGNATURE:----lklaogGUjg70ZM33i8nnC3Inwxo6dX9fpTR6jgD6cWj3HBUX5z17GOiTcNVLy5nr1+rqGR1ZW63fmUZNtHQt47WpoylbI+2n4j2yu48MuoRzw560h2X+4MKA05WVXK6gCKSvhUEcTfL9qGJqWfRJ5sTyLnVEQH3v45tNjoVhY2IEc/fjDHSf5ALBnrBDGCKklcH7lO1zR1xCevCO7vnLVZO9GdIZJc5kxH38/g222m/eYSHZg2KkxJNdwIXxPZ0WxiIHmbMF2iiXFIEEwmRPuafNpEiRZqfBAC41Pa/85YozIWZZtK572cJDmow9H4p3WViIsgx+4mGRwOLfbvPKcZY880rRYMgVEY2LFasJZTHx86tFL0bsqJY9ERSZFLwx3DVfax+nVwqG3s1e2D3W42cV2pmfKCdAHLKrnBv3ezbeDi1ACp8vkTRK6Ov/7r9NKxkbxhdlltTteHO4HtB1ER5LI6NEigw6msJ5vEFIe7KWmnXbeHLzO06WuuRzDV9c2zB/AzQgUv7YOuoHNJAcopT0HYvtsLdwxu5Bj2JNYBL8QOT0UzE/7SV3Ad9boyyVH17lI7tuXmW3xZ+GLeVjAwpU29S+aLLF/tCmwZ5uzPmqRn5wudZHRig4xiZIqyhU6sLtzsJv9CP1WBAQZCf26qoAzhsDLMqIYlTci082BZ0=----ATTACHMENT:----MTU4NTAzNTU4NDgxODE4NyA2OTgyOTUyNDIxODg3NjYyIDI1ODExOTMyOTY2ODg1Nzk=