>bRZ慰'r9B#̙Qu@~~W189%Jhxf';nz]ojm7ćSn$fK!&IT3[;`ڿ /_4 ގtʅ Qu !aPW'ƒ1~ֹ4Qt  ?R~՝G2;+NmRo z9};rvV7f]"E 8i~1Mͥ+˵<͞Czʴgx6I8ح+)ѷۆH#*$D wr+J94sSV0LRo z9};rv s<$_q+L^n@Fz\V2Drւ"QŽ9I`fAi6_&ح@;2-et%XsKRx^' &0؃xLŭ:Xy4z+tUR \(5R 3ޑEӥ] s%v=4g2Hd7ZAOaB;jVi=qEŔBqߨfÙJC#CHlkTIt{Zo SrhPBtW9xJ!AC*rjR!%.p6HSftcl{F`"MԢٌ1yW= ^w9՞D|,)waK:fåwv+z}6yM6A1onb&3A>VCE>z~4Swdp2"[ 5Tٽu1=&-QۚXd?`u(w&o3|Q=;6h^r.1kufL82zʚ 殺I8v딆Wl,83,S:cqeڙ.C%+XHW 09 :QckVMcC2h?>Gĸ\?2=٫&YFXL7;g_W)0X$*Pt%dtAAy`BzQo~jN !nb,tMvȠ|s819x 'm>#3=!vX+[h=| ,-f׻:+ HJj08 dly5 ]?w E[ Z .vwxNDmpC.ޤ RKj߷4 zAjVZj:-Tuw:w}9n1a 5Nz"LQh wsc~/>tp3\3))'u<9*]--vYH0G_F.TE6ZW6uTv>0Ȍ9%;͌㎦[MDVZ-}d!>ƴlѯ4ܚ/0# Q2 D4bgkݦLUHPSNBxT?dshz_B?YM='S 26r_&߿~T|ol%p);d/z}i+֬:gP;;T=ذ_"8hhez ssvv > to(Cq]^ =};U*(j-%a좛j_-J!󧰸eGl$(r~Ymdv GG7+{gv*'cS\N_јu21HwOT ׮1bR>d?3裵yRUǘ-fU[_B q`w VuOG0]d?A"Dw*56)LWi&NZ_(,[PUw6@'-+r?}Y]O_ wgFN5K]O?el}]$֙$C#,f҃jǕ" "*:' I?x 4[Ј>VJ"[(@ShNX28:Mzzcڢ)/bz?ep!(/tÙ(&HړdǤE0u?",?|*h.12I\(bN6eAjx. =j.Z{{hLH lK"^ucM&wxj.[R&j*L,Ƥ?ڴWOӋtywPOe"Q֭z`HpKuYйnL߶3Hn)y.&&;\ts] YIF{lgʙ$&-I`,ʮaQnKo,sa劉+?,-l$ BYDSŰ;Lv$u:ykoi7R>$ƂH3^E:PhU\wܓ.-x9!lCys8~Մ return; } // Add only up to N pending promises. $concurrency = is_callable($this->concurrency) ? call_user_func($this->concurrency, count($this->pending)) : $this->concurrency; $concurrency = max($concurrency - count($this->pending), 0); // Concurrency may be set to 0 to disallow new promises. if (!$concurrency) { return; } // Add the first pending promise. $this->addPending(); // Note this is special handling for concurrency=1 so that we do // not advance the iterator after adding the first promise. This // helps work around issues with generators that might not have the // next value to yield until promise callbacks are called. while (--$concurrency && $this->advanceIterator() && $this->addPending()) { } } private function addPending(): bool { if (!$this->iterable || !$this->iterable->valid()) { return false; } $promise = Create::promiseFor($this->iterable->current()); $key = $this->iterable->key(); // Iterable keys may not be unique, so we use a counter to // guarantee uniqueness $idx = $this->nextPendingIndex++; $this->pending[$idx] = $promise->then( function ($value) use ($idx, $key): void { if ($this->onFulfilled) { call_user_func( $this->onFulfilled, $value, $key, $this->aggregate ); } $this->step($idx); }, function ($reason) use ($idx, $key): void { if ($this->onRejected) { call_user_func( $this->onRejected, $reason, $key, $this->aggregate ); } $this->step($idx); } ); return true; } private function advanceIterator(): bool { // Place a lock on the iterator so that we ensure to not recurse, // preventing fatal generator errors. if ($this->mutex) { return false; } $this->mutex = true; try { $this->iterable->next(); $this->mutex = false; return true; } catch (\Throwable $e) { $this->aggregate->reject($e); $this->mutex = false; return false; } } private function step(int $idx): void { // If the promise was already resolved, then ignore this step. if (Is::settled($this->aggregate)) { return; } unset($this->pending[$idx]); // Only refill pending promises if we are not locked, preventing the // EachPromise to recursively invoke the provided iterator, which // cause a fatal error: "Cannot resume an already running generator" if ($this->advanceIterator() && !$this->checkIfFinished()) { // Add more pending promises if possible. $this->refillPending(); } } private function checkIfFinished(): bool { if (!$this->pending && !$this->iterable->valid()) { // Resolve the promise if there's nothing left to do. $this->aggregate->resolve(null); return true; } return false; } }