public function executeStaticMethod(string $class, string $method, array $args = []) : Awaitable { return new Task($this->executor->execute(function () use($class, $method, $args) { yield from $this->transmitter->send(['class' => $class, 'method' => $method, 'args' => $args], SocketTransmitter::TYPE_DATA); list($type, $payload) = (yield from $this->transmitter->receive()); if ($type === SocketTransmitter::TYPE_DATA) { return $payload; } })); }
/** * @codeCoverageIgnore */ protected function processWork() : \Generator { $transmitter = new SocketTransmitter(new SocketStream($this->socket)); while (true) { list($type, $payload) = (yield from $transmitter->receive()); if ($type === SocketTransmitter::TYPE_EXIT) { yield from $transmitter->send($payload, $type); break; } try { if (isset($payload['func'])) { if (\substr($payload['func'], 0, 1) === '@') { $result = \substr($payload['func'], 1)(...$payload['args'] ?? []); } else { $result = $payload['func'](...$payload['args'] ?? []); } } elseif (isset($payload['class']) && isset($payload['method'])) { $result = $payload['class']::{$payload['method']}(...$payload['args'] ?? []); } else { throw new \RuntimeException('No callable target passed to threaded worker'); } } catch (\Throwable $e) { yield from $transmitter->sendError($e); continue; } yield from $transmitter->send($result, SocketTransmitter::TYPE_DATA); } }
protected function handleHandshake(SocketStream $socket) : \Generator { $transmitter = new SocketTransmitter($socket); list($type, $message) = (yield from $transmitter->receive()); if ($type !== SocketTransmitter::TYPE_HANDSHAKE) { throw new \RuntimeException('Failed to perform worker handshake'); } $id = (int) $message; $this->workers[$id]->start($socket, $transmitter); }
private static function handshake(SocketStream $socket) : \Generator { $transmitter = new SocketTransmitter($socket); list($type, $data) = (yield from $transmitter->receive()); if ($type !== SocketTransmitter::TYPE_HANDSHAKE || !isset($data['id'])) { return $socket->close(); } $id = $data['id']; if (empty(self::$handshakes[$id])) { return $socket->close(); } list($worker, $defer) = self::$handshakes[$id]; unset(self::$handshakes[$id]); if (empty(self::$handshakes) && self::$serverAwait !== null) { self::$serverAwait->cancel(new PoolShutdownException('Handshakes done')); } $worker->connect($socket, $transmitter); self::$sharedWorkers[$id] = $worker; $defer->resolve($worker); }
throw new \Error($message, $severity); } }); require_once $_SERVER['autoloader']; $exitCode = 1; Loop::execute(function () use(&$exitCode) { new Coroutine(function () use(&$exitCode) { $id = (string) $_SERVER['id']; list($protocol, $peer) = \explode('://', (string) $_SERVER['ipc'], 2); $factory = new SocketFactory($peer, $protocol); $socket = (yield $factory->createSocketStream(2)); $transmitter = new SocketTransmitter($socket); try { yield from $transmitter->send(['id' => $id], SocketTransmitter::TYPE_HANDSHAKE); while (true) { list($type, $payload) = (yield from $transmitter->receive()); if ($type === SocketTransmitter::TYPE_EXIT) { yield from $transmitter->send($payload, $type); $socket->close(); $exitCode = 0; break; } try { if (isset($payload['func'])) { if (\substr($payload['func'], 0, 1) === '@') { $result = \substr($payload['func'], 1)(...$payload['args'] ?? []); } else { $result = $payload['func'](...$payload['args'] ?? []); } } elseif (isset($payload['class']) && isset($payload['method'])) { $result = $payload['class']::{$payload['method']}(...$payload['args'] ?? []);