/** * Starts the context execution. * * @throws \Icicle\Concurrent\Exception\ForkException If forking fails. * @throws \Icicle\Stream\Exception\FailureException If creating a socket pair fails. */ public function start() { if (0 !== $this->oid) { throw new StatusError('The context has already been started.'); } list($parent, $child) = Stream\pair(); switch ($pid = pcntl_fork()) { case -1: // Failure throw new ForkException('Could not fork process!'); case 0: // Child // @codeCoverageIgnoreStart // Create a new event loop in the fork. Loop\loop($loop = Loop\create(false)); $channel = new ChannelledStream($pipe = new DuplexPipe($parent)); fclose($child); $coroutine = new Coroutine($this->execute($channel)); $coroutine->done(); try { $loop->run(); $code = 0; } catch (\Throwable $exception) { $code = 1; } $pipe->close(); exit($code); // @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd default: // Parent $this->pid = $pid; $this->oid = posix_getpid(); $this->channel = new ChannelledStream($this->pipe = new DuplexPipe($child)); fclose($parent); } }
/** * Spawns the thread and begins the thread's execution. * * @throws \Icicle\Concurrent\Exception\StatusError If the thread has already been started. * @throws \Icicle\Concurrent\Exception\ThreadException If starting the thread was unsuccessful. * @throws \Icicle\Stream\Exception\FailureException If creating a socket pair fails. */ public function start() { if (0 !== $this->oid) { throw new StatusError('The thread has already been started.'); } $this->oid = getmypid(); list($channel, $this->socket) = Stream\pair(); $this->thread = new Internal\Thread($this->socket, $this->function, $this->args); if (!$this->thread->start(PTHREADS_INHERIT_INI | PTHREADS_INHERIT_FUNCTIONS | PTHREADS_INHERIT_CLASSES)) { throw new ThreadException('Failed to start the thread.'); } $this->channel = new ChannelledStream($this->pipe = new DuplexPipe($channel)); }