/** * Executes libuv callbacks and ensures that the loop keeps running until the callback has been invoked. * * Arguments must contain 1 closure that is assumed to be the callback being invoked by libuv. * * @param string $func The name of the uv function to be called. * @param mixed $args Arguments to be passed to the function. * @return mixed Value returned / error thrown by the passed callback. * * @throws \InvalidArgumentException When no callback argument has been passed. */ public function handleCallback(string $func, ...$args) : Awaitable { $defer = new Deferred(); $defer->when(function () { $this->watchersReferenced--; }); for ($len = \count($args), $i = 0; $i < $len; $i++) { if ($args[$i] instanceof \Closure) { $callback = $args[$i]; $args[$i] = function (...$args) use($defer, $callback) { try { $result = $callback(...$args); } catch (\Throwable $e) { return $defer->fail($e); } if ($result instanceof \Generator) { $defer->resolve(new Coroutine($result)); } else { $defer->resolve($result); } }; break; } } if (!isset($callback)) { return new Failure(new \InvalidArgumentException('Missing callback argument')); } $this->watchersReferenced++; try { $func(...\array_merge([$this->loop], $args)); } catch (\Throwable $e) { $this->watchersReferenced--; return new Failure($e); } return $defer; }
public function handleCallback(string $func, ...$args) : Awaitable { $request = null; $defer = new Deferred(function () use(&$request) { if (\is_resource($request)) { \eio_cancel($request); } }); $defer->when(function () { $this->pending--; if (!$this->pending) { Loop::disable($this->watcherId); } }); for ($len = \count($args), $i = 0; $i < $len; $i++) { if ($args[$i] instanceof \Closure) { $callback = $args[$i]; $args[$i] = function (...$args) use($defer, $callback) { try { $result = $callback(...$args); } catch (\Throwable $e) { return $defer->fail($e); } if ($result instanceof \Generator) { $defer->resolve(new Coroutine($result)); } else { $defer->resolve($result); } }; break; } } if (!isset($callback)) { throw new \InvalidArgumentException('Missing callback argument'); } if (!$this->pending) { if ($this->watcherId === null) { $this->watcherId = Loop::onReadable(self::$eio, self::$callback); } else { Loop::enable($this->watcherId); } } $this->pending++; try { $request = $func(...$args); } catch (\Throwable $e) { $this->pending--; if (!$this->pending) { Loop::disable($this->watcherId); } return new Failure($e); } return $defer; }