Exemple #1
0
 /**
  * Start the coroutine.
  *
  * @param StrandInterface $strand The strand that is executing the coroutine.
  */
 public function call(StrandInterface $strand)
 {
     $this->strand = $strand;
     $this->strand->suspend();
     foreach ($this->coroutines as $index => $coroutine) {
         $this->values[$index] = null;
         $this->substrands[$index] = $substrand = $strand->kernel()->execute($coroutine);
         $substrand->on('success', function ($strand, $value) use($index) {
             $this->values[$index] = $value;
         });
         $substrand->on('error', function ($strand, $exception, $preventDefault) {
             $this->exception = $exception;
             $preventDefault();
         });
         $substrand->on('terminate', function () {
             $this->exception = new StrandTerminatedException();
         });
         $substrand->on('exit', function () use($index) {
             unset($this->substrands[$index]);
             if (!$this->strand) {
                 return;
             } elseif ($this->exception) {
                 $this->strand->resumeWithException($this->exception);
                 $this->strand = null;
             } elseif (!$this->substrands) {
                 $this->strand->resumeWithValue($this->values);
                 $this->strand = null;
             }
         });
     }
 }
Exemple #2
0
 /**
  * Invoked when tick() is called for the first time.
  *
  * @param StrandInterface $strand The strand that is executing the coroutine.
  */
 public function call(StrandInterface $strand)
 {
     $strand->suspend();
     $this->timer = $strand->kernel()->eventLoop()->addTimer($this->timeout, function () use($strand) {
         $strand->resumeWithValue(null);
     });
 }
Exemple #3
0
 /**
  * Inform the coroutine that the executing strand is being terminated.
  *
  * @param StrandInterface $strand The strand that is executing the coroutine.
  */
 public function terminate(StrandInterface $strand)
 {
     $strand->emit('terminate', [$strand]);
     $strand->emit('exit', [$strand]);
     $strand->removeAllListeners();
     $strand->suspend();
 }
Exemple #4
0
 /**
  * Inform the coroutine that the executing strand is being terminated.
  *
  * @param StrandInterface $strand The strand that is executing the coroutine.
  */
 public function terminate(StrandInterface $strand)
 {
     if (!$this->timer) {
         // Stop termination of the strand and instead propagate a timeout exception.
         $strand->throwException(new TimeoutException());
     }
 }
Exemple #5
0
 /**
  * Start the coroutine.
  *
  * @param StrandInterface $strand The strand that is executing the coroutine.
  */
 public function call(StrandInterface $strand)
 {
     $strand->suspend();
     $this->promise->then(function ($value) use($strand) {
         if ($this->promise) {
             $strand->resumeWithValue($value);
         }
     }, function ($reason) use($strand) {
         if ($this->promise) {
             $strand->resumeWithException($this->adaptReasonToException($reason));
         }
     });
 }
 /**
  * Resume execution of a suspended coroutine by passing it an exception.
  *
  * @param StrandInterface $strand    The strand that is executing the coroutine.
  * @param Exception       $exception The exception to send to the coroutine.
  */
 public function resumeWithException(StrandInterface $strand, Exception $exception)
 {
     try {
         $this->generator->throw($exception);
         $valid = $this->generator->valid();
     } catch (Exception $e) {
         $strand->throwException($e);
         return;
     }
     if ($valid) {
         $strand->call($this->generator->current());
     } elseif (self::$hasReturnValue) {
         $strand->returnValue($this->generator->getReturn());
     } else {
         $strand->returnValue(null);
     }
 }
Exemple #7
0
 /**
  * Start the coroutine.
  *
  * @param StrandInterface $strand The strand that is executing the coroutine.
  */
 public function call(StrandInterface $strand)
 {
     $method = [$strand->kernel()->api(), $this->name];
     if (!is_callable($method)) {
         $strand->throwException(new BadMethodCallException('The kernel API does not have an operation named "' . $this->name . '".'));
         return;
     }
     $strand->pop();
     $arguments = $this->arguments;
     array_unshift($arguments, $strand);
     // If the kernel API implementation returns a non-null value it is
     // treated as a coroutine to be executed. This allows implementation of
     // kernel API operations to be implemented as generators.
     $coroutine = call_user_func_array($method, $arguments);
     if (null !== $coroutine) {
         $strand->call($coroutine);
     }
 }
Exemple #8
0
 /**
  * Finalize the coroutine.
  *
  * This method is invoked after the coroutine is popped from the call stack.
  *
  * @param StrandInterface $strand The strand that is executing the coroutine.
  */
 public function finalize(StrandInterface $strand)
 {
     foreach ($this->substrands as $strand) {
         $strand->removeListener('exit', [$this, 'onStrandExit']);
     }
 }
Exemple #9
0
 /**
  * Stop the coroutine kernel / event-loop.
  *
  * The React event-loop can optionally be stopped when all strands have been
  * terminated.
  *
  * @param StrandInterface $strand        The currently executing strand.
  * @param boolean         $stopEventLoop Indicates whether or not the React event-loop should also be stopped.
  */
 public function stop(StrandInterface $strand, $stopEventLoop = true)
 {
     $strand->terminate();
     $strand->kernel()->stop($stopEventLoop);
 }
Exemple #10
0
 /**
  * Resume execution of a suspended coroutine by passing it an exception.
  *
  * @param StrandInterface $strand    The strand that is executing the coroutine.
  * @param Exception       $exception The exception to send to the coroutine.
  */
 public function resumeWithException(StrandInterface $strand, Exception $exception)
 {
     $strand->throwException($exception);
 }