* @copyright 2016-2020 Daniil Gentili * @license https://opensource.org/licenses/MIT MIT */ namespace danog\Loop\Traits; use Amp\Coroutine; use Amp\Deferred; use Amp\Promise; /** * Signal loop helper trait. * * @author Daniil Gentili */ trait SignalLoop { /** * Signal deferred. * * @var ?Deferred */ private $signalDeferred; /** * Send signal to loop. * * @param mixed|\Throwable $what Data to signal * * @return void */ public function signal($what): void { if ($this->signalDeferred) { $deferred = $this->signalDeferred; $this->signalDeferred = null; if ($what instanceof \Throwable) { $deferred->fail($what); } else { $deferred->resolve($what); } } } /** * Resolve the promise or return|throw the signal. * * @param Promise|\Generator $promise The original promise or generator * * @return Promise * * @template T * * @psalm-param Promise|\Generator,mixed,Promise|T> $promise The original promise or generator * * @psalm-return Promise */ public function waitSignal($promise): Promise { if ($promise instanceof \Generator) { $promise = new Coroutine($promise); } $this->signalDeferred = new Deferred(); $combinedPromise = $this->signalDeferred->promise(); $promise->onResolve( function () use ($promise) { if ($this->signalDeferred !== null) { $deferred = $this->signalDeferred; $this->signalDeferred = null; $deferred->resolve($promise); } } ); return $combinedPromise; } }