@@ -42,6 +42,8 @@ final class AmpResponse implements ResponseInterface
4242 private $ canceller ;
4343 private $ onProgress ;
4444
45+ private static $ delay ;
46+
4547 /**
4648 * @internal
4749 */
@@ -171,18 +173,21 @@ private static function perform(ClientState $multi, array &$responses = null): v
171173 */
172174 private static function select (ClientState $ multi , float $ timeout ): int
173175 {
174- $ selected = 1 ;
175- $ delay = Loop::delay (1000 * $ timeout , static function () use (&$ selected ) {
176- $ selected = 0 ;
177- Loop::stop ();
178- });
179- Loop::run ();
176+ $ start = microtime (true );
177+ $ remaining = $ timeout ;
180178
181- if ( $ selected ) {
182- Loop::cancel ( $ delay );
183- }
179+ while ( true ) {
180+ self :: $ delay = Loop::delay ( 1000 * $ remaining , [Loop::class, ' stop ' ] );
181+ Loop:: run ();
184182
185- return $ selected ;
183+ if (null === self ::$ delay ) {
184+ return 1 ;
185+ }
186+
187+ if (0 >= $ remaining = $ timeout - microtime (true ) + $ start ) {
188+ return 0 ;
189+ }
190+ }
186191 }
187192
188193 private static function generateResponse (Request $ request , AmpClientState $ multi , string $ id , array &$ info , array &$ headers , CancellationTokenSource $ canceller , array &$ options , \Closure $ onProgress , &$ handle , ?LoggerInterface $ logger )
@@ -192,7 +197,7 @@ private static function generateResponse(Request $request, AmpClientState $multi
192197 $ request ->setInformationalResponseHandler (static function (Response $ response ) use (&$ activity , $ id , &$ info , &$ headers ) {
193198 self ::addResponseHeaders ($ response , $ info , $ headers );
194199 $ activity [$ id ][] = new InformationalChunk ($ response ->getStatus (), $ response ->getHeaders ());
195- Loop:: defer ([Loop::class, ' stop ' ] );
200+ self :: stopLoop ( );
196201 });
197202
198203 try {
@@ -210,7 +215,7 @@ private static function generateResponse(Request $request, AmpClientState $multi
210215 if ('HEAD ' === $ response ->getRequest ()->getMethod () || \in_array ($ info ['http_code ' ], [204 , 304 ], true )) {
211216 $ activity [$ id ][] = null ;
212217 $ activity [$ id ][] = null ;
213- Loop:: defer ([Loop::class, ' stop ' ] );
218+ self :: stopLoop ( );
214219
215220 return ;
216221 }
@@ -222,7 +227,7 @@ private static function generateResponse(Request $request, AmpClientState $multi
222227 $ body = $ response ->getBody ();
223228
224229 while (true ) {
225- Loop:: defer ([Loop::class, ' stop ' ] );
230+ self :: stopLoop ( );
226231
227232 if (null === $ data = yield $ body ->read ()) {
228233 break ;
@@ -241,7 +246,7 @@ private static function generateResponse(Request $request, AmpClientState $multi
241246 $ info ['download_content_length ' ] = $ info ['size_download ' ];
242247 }
243248
244- Loop:: defer ([Loop::class, ' stop ' ] );
249+ self :: stopLoop ( );
245250 }
246251
247252 private static function followRedirects (Request $ originRequest , AmpClientState $ multi , array &$ info , array &$ headers , CancellationTokenSource $ canceller , array $ options , \Closure $ onProgress , &$ handle , ?LoggerInterface $ logger )
@@ -402,4 +407,14 @@ private static function getPushedResponse(Request $request, AmpClientState $mult
402407 return $ response ;
403408 }
404409 }
410+
411+ private static function stopLoop (): void
412+ {
413+ if (null !== self ::$ delay ) {
414+ Loop::cancel (self ::$ delay );
415+ self ::$ delay = null ;
416+ }
417+
418+ Loop::defer ([Loop::class, 'stop ' ]);
419+ }
405420}
0 commit comments