protected function createReadWatcher() : callable { return function ($id) { while (!$this->pendingReads->isEmpty()) { $read = $this->pendingReads->bottom(); if ($read->disabled) { $this->pendingReads->dequeue(); continue; } $len = \strlen($this->readBuffer); try { $chunk = $this->fillReadBuffer($len, $read->length); } catch (\Throwable $e) { $this->readerEnabled = false; Loop::disable($id); while (!$this->pendingReads->isEmpty()) { $this->pendingReads->dequeue()->fail($e); } return; } if ($chunk === $this) { return; } if ($chunk === null) { $this->readerEnabled = false; Loop::disable($id); while (!$this->pendingReads->isEmpty()) { $this->pendingReads->dequeue()->resolve(null); } return; } $read = $this->pendingReads->dequeue(); if ($len > $read->length) { $this->readBuffer = \substr($chunk, $read->length); $read->resolve(\substr($chunk, 0, $read->length)); } else { $this->readBuffer = ''; $read->resolve($chunk); } } $this->readerEnabled = false; Loop::disable($id); }; }
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; }
protected function createWriteWatcher() : callable { return function ($id) { while (!$this->pendingWrites->isEmpty()) { $write = $this->pendingWrites->bottom(); if ($write->disabled) { $this->pendingWrites->dequeue(); continue; } try { $write->bytes = $this->writeBytes($write->bytes); } catch (\Throwable $e) { $this->writerEnabled = false; Loop::disable($id); while (!$this->pendingWrites->isEmpty()) { $this->pendingWrites->dequeue()->fail($e); } return; } if ($write->bytes === '') { $this->pendingWrites->dequeue()->resolve($write->length); } else { return; } } $this->writerEnabled = false; Loop::disable($id); }; }