loop = $loop; $this->future = $future; $this->context = $future->createContext(function() { $this->cancelled = true; }); $this->resolve = API\Future\resolver($future, $this->context); $this->reject = API\Future\rejecter($future, $this->context); $this->reduce = API\Future\reducer($future, $this->context); } /** * Iterate over $gen, a \Generator yielding promises * * @param Generator $gen * @return mixed promise */ function __invoke(Generator $gen) { $this->cancelled = false; foreach ($gen as $promise) { if ($this->cancelled) { break; } $this->give($promise, $gen); } #($this->loop)(); if (!$this->cancelled) { $this->result = $gen->getReturn(); } if (isset($this->result)) { ($this->resolve)($this->result); } else { ($this->reject)("Cancelled"); } return $this->context->promise(); } /** * Promise handler * * @param mixed $promise * @param Generator $gen */ private function give($promise, Generator $gen) { if ($promise instanceof \Traversable) { $promise = iterator_to_array($promise); } if (is_array($promise)) { $promise = ($this->reduce)($promise); } $this->future->handlePromise($promise, function($result) use($gen) { if (($promise = $gen->send($result))) { $this->give($promise, $gen); } }, function($error) use($gen) { $gen->throw(exception($error)); }); /* FIXME: external loop */ ($this->loop)(); } }