Example #1
0
 /**
  * Throws an error in the observable.
  *
  * @param \Throwable $reason
  */
 public function fail(\Throwable $reason)
 {
     if (null !== $this->started) {
         $this->started->reject(new CompletedError());
     }
     $this->delayed->reject($reason);
 }
Example #2
0
 /**
  * Marks the observable as complete with the given error.
  *
  * @param \Throwable $exception
  */
 public function fail(\Throwable $exception)
 {
     if (null === $this->observable) {
         return;
     }
     $this->observable = null;
     $this->failed = true;
     $this->delayed->reject($exception);
 }
Example #3
0
 /**
  * @throws \Icicle\Concurrent\Exception\ProcessException If starting the process fails.
  * @throws \Icicle\Concurrent\Exception\StatusError If the process is already running.
  */
 public function start()
 {
     if (null !== $this->delayed) {
         throw new StatusError('The process has already been started.');
     }
     $this->delayed = new Delayed();
     $fd = [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'a'], ['pipe', 'w']];
     $nd = 0 === strncasecmp(PHP_OS, 'WIN', 3) ? 'NUL' : '/dev/null';
     $command = sprintf('(%s) 3>%s; code=$?; echo $code >&3; exit $code', $this->command, $nd);
     $this->process = proc_open($command, $fd, $pipes, $this->cwd ?: null, $this->env ?: null, $this->options);
     if (!is_resource($this->process)) {
         throw new ProcessException('Could not start process.');
     }
     $this->oid = getmypid();
     $status = proc_get_status($this->process);
     if (!$status) {
         proc_close($this->process);
         $this->process = null;
         throw new ProcessException('Could not get process status.');
     }
     $this->pid = $status['pid'];
     $this->stdin = new WritablePipe($pipes[0]);
     $this->stdout = new ReadablePipe($pipes[1]);
     $this->stderr = new ReadablePipe($pipes[2]);
     $stream = $pipes[3];
     stream_set_blocking($stream, 0);
     $this->poll = Loop\poll($stream, function ($resource) {
         if (!is_resource($resource) || feof($resource)) {
             $this->close($resource);
             $this->delayed->reject(new ProcessException('Process ended unexpectedly.'));
         } else {
             $code = fread($resource, 1);
             $this->close($resource);
             if (!strlen($code) || !is_numeric($code)) {
                 $this->delayed->reject(new ProcessException('Process ended without providing a status code.'));
             } else {
                 $this->delayed->resolve((int) $code);
             }
         }
         $this->poll->free();
     });
 }
Example #4
0
 /**
  * {@inheritdoc}
  */
 public function read(int $length = 0, string $byte = null, float $timeout = 0) : \Generator
 {
     while (null !== $this->delayed) {
         (yield $this->delayed);
     }
     if (!$this->isReadable()) {
         throw new UnreadableException('The stream is no longer readable.');
     }
     $this->length = $length;
     if (0 > $this->length) {
         throw new InvalidArgumentError('The length should be a positive integer.');
     }
     $this->byte = strlen($byte) ? $byte[0] : null;
     if (!$this->buffer->isEmpty()) {
         $data = $this->remove();
         if (0 !== $this->hwm && $this->buffer->getLength() <= $this->hwm) {
             while (!$this->queue->isEmpty()) {
                 /** @var \Icicle\Awaitable\Delayed $delayed */
                 $delayed = $this->queue->shift();
                 $delayed->resolve();
             }
         }
         if (!$this->writable && $this->buffer->isEmpty()) {
             $this->free();
         }
         return $data;
     }
     $awaitable = $this->delayed = new Delayed();
     if ($timeout) {
         $awaitable = $this->delayed->timeout($timeout);
     }
     try {
         $data = (yield $awaitable);
     } finally {
         $this->delayed = null;
     }
     return $data;
 }
Example #5
0
 /**
  * Notifies the placeholder that the consumer is ready.
  */
 public function ready()
 {
     if (0 === --$this->waiting) {
         $this->delayed->resolve();
     }
 }
Example #6
0
 /**
  * Returns an observable that emits a value every $interval seconds, up to $count times (or indefinitely if $count
  * is 0). The value emitted is an integer of the number of times the observable emitted a value.
  *
  * @param float|int $interval Time interval between emitted values in seconds.
  * @param int $count Use 0 to emit values indefinitely.
  *
  * @return \Icicle\Observable\Observable
  */
 function interval(float $interval, int $count = 0) : Observable
 {
     return new Emitter(function (callable $emit) use($interval, $count) : \Generator {
         if (0 > $count) {
             throw new InvalidArgumentError('The number of times to emit must be a non-negative value.');
         }
         $start = microtime(true);
         $i = 0;
         $delayed = new Delayed();
         $timer = Loop\periodic($interval, function () use(&$delayed, &$i) {
             $delayed->resolve(++$i);
             $delayed = new Delayed();
         });
         try {
             while (0 === $count || $i < $count) {
                 yield from $emit($delayed);
             }
         } finally {
             $timer->stop();
         }
         return microtime(true) - $start;
     });
 }
Example #7
0
 /**
  * Throws an error in the observable.
  *
  * @param \Throwable $reason
  */
 public function fail(\Throwable $reason)
 {
     $this->delayed->reject($reason);
 }