defer() public static method

The deferred callable MUST be executed in the next tick of the event loop and before any other type of watcher. Order of enabling MUST be preserved when executing the callbacks.
public static defer ( callable $callback, mixed $data = null ) : string
$callback callable
$data mixed Arbitrary data given to the callback function as the `$data` parameter.
return string An unique identifier that can be used to cancel, enable or disable the watcher.
Example #1
0
 public function when(callable $onResolved)
 {
     try {
         $onResolved($this->error);
     } catch (\Throwable $e) {
         Loop::defer(function () use($e) {
             throw $e;
         });
     }
 }
Example #2
0
 /**
  * {@inheritdoc}
  */
 public function when(callable $onResolved)
 {
     try {
         $onResolved($this->exception, null);
     } catch (\Throwable $exception) {
         Loop::defer(static function () use($exception) {
             throw $exception;
         });
     }
 }
Example #3
0
 protected function runServer(callable $server, callable $client) : \Generator
 {
     $socket = (yield $this->serverFactory->createSocketServer());
     try {
         return (yield new AwaitAll([new Coroutine($this->serverTask($socket, $server)), new Coroutine($this->clientTask($socket, $client))]));
     } finally {
         Loop::defer(function () use($socket) {
             $socket->close();
         });
     }
 }
Example #4
0
 /**
  * Calls each callback in the queue, passing the provided values to the function.
  *
  * @param \Throwable|null $exception
  * @param mixed $value
  */
 public function __invoke($exception, $value)
 {
     foreach ($this->queue as $callback) {
         try {
             $callback($exception, $value);
         } catch (\Throwable $exception) {
             Loop::defer(static function () use($exception) {
                 throw $exception;
             });
         }
     }
 }
Example #5
0
 /**
  * @param callable(callable(mixed $value): Promise $emit): \Generator $emitter
  *
  * @throws \Error Thrown if the callable does not return a Generator.
  */
 public function __construct(callable $emitter)
 {
     $result = $emitter($this->callableFromInstanceMethod("emit"));
     if (!$result instanceof \Generator) {
         throw new \Error("The callable did not return a Generator");
     }
     Loop::defer(function () use($result) {
         $coroutine = new Coroutine($result);
         $coroutine->when(function ($exception, $value) {
             if ($this->resolved) {
                 return;
             }
             if ($exception) {
                 $this->fail($exception);
                 return;
             }
             $this->resolve($value);
         });
     });
 }
Example #6
0
 /**
  * Internal resolution
  *
  * @param $callback
  *
  * @throws \Exception|\Throwable
  */
 private function resolve($callback)
 {
     try {
         $callback();
     } catch (\Throwable $exception) {
         if ($this->hasActiveLoop()) {
             Loop::defer(static function () use($exception) {
                 throw $exception;
             });
         }
         throw $exception;
     } catch (\Exception $exception) {
         if ($this->hasActiveLoop()) {
             Loop::defer(static function () use($exception) {
                 throw $exception;
             });
         }
         throw $exception;
     }
 }
Example #7
0
 protected function advance($val)
 {
     while (($this->valid = $this->generator->valid()) && $val instanceof Promise) {
         $done = false;
         $val->when(function (\Throwable $e = null, $v = null) use(&$val, &$done) {
             if (!$this->valid || !self::$alive) {
                 return;
             }
             if ($e) {
                 $this->dispose($e);
             } elseif ($done) {
                 $this->running = true;
                 try {
                     $this->advance($this->generator->send($v));
                     $this->running = false;
                     if ($this->error) {
                         $this->dispose($this->error);
                     }
                 } catch (\Throwable $e) {
                     $this->running = false;
                     $this->dispose($e);
                 }
             } else {
                 $done = true;
                 $val = $v;
             }
         });
         if (!$done || !self::$alive) {
             $done = true;
             $this->promise = $val;
             return;
         }
         $this->running = true;
         try {
             $val = $this->generator->send($val);
             $this->running = false;
             if ($this->error) {
                 return $this->dispose($this->error);
             }
         } catch (\Throwable $e) {
             $this->running = false;
             return $this->dispose($e);
         }
     }
     if ($this->valid) {
         return Loop::defer(function ($id, $val) {
             if (!$this->valid || !self::$alive) {
                 return;
             }
             $this->running = true;
             try {
                 $this->advance($this->generator->send($val));
                 $this->running = false;
                 if ($this->error) {
                     $this->dispose($this->error);
                 }
             } catch (\Throwable $e) {
                 $this->running = false;
                 $this->dispose($e);
             }
         }, $val);
     }
     if ($this->error) {
         return $this->dispose($this->error);
     }
     if ($this->state === self::PENDING) {
         $this->resolve($this->generator->getReturn());
     }
 }
Example #8
0
 /**
  * Fail the awaitable with the given error.
  * 
  * @param \Throwable $error
  * 
  * @throws \RuntimeException If the awaitable has already been resolved or failed.
  */
 protected function fail(\Throwable $error)
 {
     if ($this->state !== Awaitable::PENDING) {
         return;
     }
     $this->state = Awaitable::FAILED;
     $this->result = $error;
     if ($this->callbacks) {
         try {
             foreach ($this->callbacks as $callback) {
                 try {
                     $callback($error);
                 } catch (\Throwable $ex) {
                     Loop::defer(function () use($ex) {
                         throw $ex;
                     });
                 }
             }
         } finally {
             $this->callbacks = null;
         }
     }
 }
Example #9
0
 protected function dispose(\Throwable $e)
 {
     if ($this->promise) {
         $promise = $this->promise;
         $this->promise = null;
         Loop::defer(function () use($promise, $e) {
             $promise->cancel($e);
         });
     }
     $this->error = null;
     while ($this->valid = $this->generator->valid() && self::$alive) {
         $this->running = true;
         try {
             return $this->advance($this->generator->throw($e));
         } catch (\Throwable $e) {
             // Continue loop switching to the outer exception.
         } finally {
             $this->running = false;
         }
     }
     if (!self::$alive || !$this->valid && $this->state === Awaitable::PENDING) {
         $this->fail($e);
     }
 }