The event loop should exit the run method when only unreferenced watchers are still being monitored. Watchers
are all referenced by default.
public static unreference ( string $watcherId ) : void | ||
$watcherId | string | The watcher identifier. |
리턴 | void |
public function run(Container $container, callable $action) { $logger = LoopConfig::getLogger(); if ($this->running === 0) { foreach ($this->loggers as $handler) { $logger->addHandler($handler); } } $this->running++; try { $buffer = ''; if ($this->ipc) { ob_start(function (string $data, int $phase) use(&$buffer) { $buffer .= $data; return ''; }, 1, \PHP_OUTPUT_HANDLER_FLUSHABLE); } Loop::execute(function () use($container, $action, $logger, &$buffer) { Loop::setErrorHandler(function (\Throwable $e) use($logger) { $logger->critical('', ['exception' => $e]); }); $watcher = Loop::repeat(500, function () use(&$buffer, $logger) { if ($buffer !== '') { try { $this->ipc->sendOutput($buffer); } finally { $buffer = ''; } } }); Loop::unreference($watcher); if ($this->contextName === 'development') { $locator = $container->get(ResourceLocator::class); $watcher = Loop::repeat(5000, function () use($locator) { $locator->syncFiles(); }); Loop::unreference($watcher); } if ($this->ipc) { $this->ipc->run(); } $signal = function () { if ($this->ipc) { $this->ipc->stop(); } Loop::stop(); }; // Shutdown on SIGTERM. try { Loop::onSignal(15, $signal); } catch (UnsupportedFeatureException $e) { // signal handling is not available... } $action(); }); } finally { if ($this->ipc) { \ob_end_clean(); } $this->running--; if ($this->running === 0) { foreach ($this->loggers as $handler) { $logger->removeHandler($handler); } } } }
public function read(int $length = 8192) : Awaitable { if (!$this->readerEnabled) { $len = \strlen($this->readBuffer); try { $chunk = $this->fillReadBuffer($len, $length); } catch (\Throwable $e) { return new Failure($e); } if ($chunk === null) { return new Success(null); } if ($chunk !== $this) { if ($len > $length) { $this->readBuffer = \substr($chunk, $length); return new Success(\substr($chunk, 0, $length)); } $this->readBuffer = ''; return new Success($chunk); } $this->readerEnabled = true; if ($this->pendingReads === null) { $this->pendingReads = new \SplQueue(); } if ($this->readWatcher === null) { $this->readWatcher = Loop::onReadable($this->socket, $this->createReadWatcher()); } else { try { Loop::enable($this->readWatcher); } catch (InvalidWatcherException $e) { $this->readWatcher = Loop::onReadable($this->socket, $this->createReadWatcher()); } } if (!$this->readerReferenced) { Loop::unreference($this->readWatcher); } } $this->pendingReads->enqueue($read = new PendingRead($length, function () { foreach ($this->pendingReads as $read) { if (!$read->disabled) { return; } } $this->readerEnabled = false; Loop::disable($this->readWatcher); })); return $read; }
public function write(string $bytes) : Awaitable { if ($bytes === '') { if (!\is_resource($this->socket)) { return new Failure(new StreamClosedException('Socket resource unavailable')); } return new Success(0); } $len = \strlen($bytes); if (!$this->writerEnabled) { try { $bytes = $this->writeBytes($bytes); } catch (\Throwable $e) { return new Failure($e); } if ($bytes === '') { return new Success($len); } $this->writerEnabled = true; if ($this->pendingWrites === null) { $this->pendingWrites = new \SplQueue(); } if ($this->writeWatcher === null) { $this->writeWatcher = Loop::onWritable($this->socket, $this->createWriteWatcher()); } else { try { Loop::enable($this->writeWatcher); } catch (InvalidWatcherException $e) { $this->writeWatcher = Loop::onWritable($this->socket, $this->createWriteWatcher()); } } if (!$this->writerReferenced) { Loop::unreference($this->writeWatcher); } } $this->pendingWrites->enqueue($write = new PendingWrite($bytes, $len, function () { foreach ($this->pendingWrites as $write) { if (!$write->disabled) { return; } } $this->writerEnabled = false; Loop::disable($this->writeWatcher); })); return $write; }