@@ -42,6 +42,8 @@ final class AmpResponse implements ResponseInterface
42
42
private $ canceller ;
43
43
private $ onProgress ;
44
44
45
+ private static $ delay ;
46
+
45
47
/**
46
48
* @internal
47
49
*/
@@ -171,18 +173,21 @@ private static function perform(ClientState $multi, array &$responses = null): v
171
173
*/
172
174
private static function select (ClientState $ multi , float $ timeout ): int
173
175
{
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 ;
180
178
181
- if ( $ selected ) {
182
- Loop::cancel ( $ delay );
183
- }
179
+ while ( true ) {
180
+ self :: $ delay = Loop::delay ( 1000 * $ remaining , [Loop::class, ' stop ' ] );
181
+ Loop:: run ();
184
182
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
+ }
186
191
}
187
192
188
193
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
192
197
$ request ->setInformationalResponseHandler (static function (Response $ response ) use (&$ activity , $ id , &$ info , &$ headers ) {
193
198
self ::addResponseHeaders ($ response , $ info , $ headers );
194
199
$ activity [$ id ][] = new InformationalChunk ($ response ->getStatus (), $ response ->getHeaders ());
195
- Loop:: defer ([Loop::class, ' stop ' ] );
200
+ self :: stopLoop ( );
196
201
});
197
202
198
203
try {
@@ -210,7 +215,7 @@ private static function generateResponse(Request $request, AmpClientState $multi
210
215
if ('HEAD ' === $ response ->getRequest ()->getMethod () || \in_array ($ info ['http_code ' ], [204 , 304 ], true )) {
211
216
$ activity [$ id ][] = null ;
212
217
$ activity [$ id ][] = null ;
213
- Loop:: defer ([Loop::class, ' stop ' ] );
218
+ self :: stopLoop ( );
214
219
215
220
return ;
216
221
}
@@ -222,7 +227,7 @@ private static function generateResponse(Request $request, AmpClientState $multi
222
227
$ body = $ response ->getBody ();
223
228
224
229
while (true ) {
225
- Loop:: defer ([Loop::class, ' stop ' ] );
230
+ self :: stopLoop ( );
226
231
227
232
if (null === $ data = yield $ body ->read ()) {
228
233
break ;
@@ -241,7 +246,7 @@ private static function generateResponse(Request $request, AmpClientState $multi
241
246
$ info ['download_content_length ' ] = $ info ['size_download ' ];
242
247
}
243
248
244
- Loop:: defer ([Loop::class, ' stop ' ] );
249
+ self :: stopLoop ( );
245
250
}
246
251
247
252
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
402
407
return $ response ;
403
408
}
404
409
}
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
+ }
405
420
}
0 commit comments