Exemple #1
0
 /**
  * @param \Generator $generator
  */
 public function __construct(Generator $generator)
 {
     $this->generator = $generator;
     parent::__construct(function (callable $resolve, callable $reject) {
         /**
          * @param mixed $value The value to send to the generator.
          * @param \Throwable|null $exception Exception object to be thrown into the generator if not null.
          */
         $this->worker = function ($value = null, Throwable $exception = null) use($resolve, $reject) {
             if ($this->paused) {
                 // If paused, mark coroutine as ready to resume.
                 $this->ready = true;
                 return;
             }
             try {
                 if ($this->initial) {
                     // Get result of first yield statement.
                     $this->initial = false;
                     $this->current = $this->generator->current();
                 } elseif (null !== $exception) {
                     // Throw exception at current execution point.
                     $this->current = $this->generator->throw($exception);
                 } else {
                     // Send the new value and execute to next yield statement.
                     $this->current = $this->generator->send($value);
                 }
                 if (!$this->generator->valid()) {
                     $resolve($this->generator->getReturn());
                     $this->close();
                     return;
                 }
                 if ($this->current instanceof Generator) {
                     $this->current = new self($this->current);
                 }
                 if ($this->current instanceof PromiseInterface) {
                     $this->current->done($this->worker, $this->capture);
                 } else {
                     Loop\queue($this->worker, $this->current);
                 }
             } catch (Throwable $exception) {
                 $reject($exception);
                 $this->close();
             }
         };
         /**
          * @param \Throwable $exception Exception to be thrown into the generator.
          */
         $this->capture = function (Throwable $exception) {
             if (null !== $this->worker) {
                 // Coroutine may have been closed.
                 ($this->worker)(null, $exception);
             }
         };
         Loop\queue($this->worker);
         return function (Throwable $exception) {
             try {
                 $current = $this->generator->current();
                 // Get last yielded value.
                 while ($this->generator->valid()) {
                     if ($current instanceof PromiseInterface) {
                         $current->cancel($exception);
                     }
                     $current = $this->generator->throw($exception);
                 }
             } finally {
                 $this->close();
             }
         };
     });
 }
Exemple #2
0
 /**
  * @param \Generator $generator
  */
 public function __construct(Generator $generator)
 {
     $this->generator = $generator;
     parent::__construct(function (callable $resolve, callable $reject) {
         $yielded = $this->generator->current();
         if (!$this->generator->valid()) {
             $resolve($this->generator->getReturn());
             $this->close();
             return;
         }
         /**
          * @param mixed $value The value to send to the generator.
          */
         $this->send = function ($value = null) use($resolve, $reject) {
             if ($this->paused) {
                 // If paused, save callable and value for resuming.
                 $this->next = [$this->send, $value];
                 return;
             }
             try {
                 // Send the new value and execute to next yield statement.
                 $yielded = $this->generator->send($value);
                 if (!$this->generator->valid()) {
                     $resolve($this->generator->getReturn());
                     $this->close();
                     return;
                 }
                 $this->next($yielded);
             } catch (Throwable $exception) {
                 $reject($exception);
                 $this->close();
             }
         };
         /**
          * @param \Throwable $exception Exception to be thrown into the generator.
          */
         $this->capture = function (Throwable $exception) use($resolve, $reject) {
             if ($this->paused) {
                 // If paused, save callable and exception for resuming.
                 $this->next = [$this->capture, $exception];
                 return;
             }
             try {
                 // Throw exception at current execution point.
                 $yielded = $this->generator->throw($exception);
                 if (!$this->generator->valid()) {
                     $resolve($this->generator->getReturn());
                     $this->close();
                     return;
                 }
                 $this->next($yielded);
             } catch (Throwable $exception) {
                 $reject($exception);
                 $this->close();
             }
         };
         $this->next($yielded);
         return function (Throwable $exception) {
             try {
                 $current = $this->generator->current();
                 // Get last yielded value.
                 if ($current instanceof PromiseInterface) {
                     $current->cancel($exception);
                 }
             } finally {
                 $this->close();
             }
         };
     });
 }