/** * Executed by Co::any() or Co::race(). * @param mixed $value * @param callable $filter self::reverse or self::fail. * @param string $message Used for failure. * @return \Generator */ public static function anyOrRace($value, callable $filter, $message) { $value = YieldableUtils::normalize($value); $yieldables = YieldableUtils::getYieldables($value); $wrapper = self::getWrapperGenerator($yieldables, $filter); try { $results = (yield $wrapper); } catch (ControlException $e) { (yield CoInterface::RETURN_WITH => $e->getValue()); } $apply = YieldableUtils::getApplier($value, $yieldables); throw new AllFailedException($message, 0, $apply($results)); }
/** * Handle resolving generators still running. * @param GeneratorContainer $gc * @return PromiseInterface */ private function processGeneratorContainerRunning(GeneratorContainer $gc) { // Check delay request yields if ($gc->key() === CoInterface::DELAY) { return $this->pool->addDelay($gc->current())->then(function () use($gc) { $gc->send(null); return $this->processGeneratorContainer($gc); }); } // Now we normalize yielded value $yielded = YieldableUtils::normalize($gc->current()); $yieldables = YieldableUtils::getYieldables($yielded, [], $this->runners); if (!$yieldables) { // If there are no yieldables, send yielded value back into generator $gc->send($yielded); // Continue return $this->processGeneratorContainer($gc); } // Chain resolver return $this->promiseAll($yieldables, $gc->key() !== CoInterface::SAFE)->then(YieldableUtils::getApplier($yielded, $yieldables, [$gc, 'send']), [$gc, 'throw_'])->then(function () use($gc, $yieldables) { // Continue $this->runners = array_diff_key($this->runners, $yieldables); return $this->processGeneratorContainer($gc); }); }