@@ -27,7 +27,10 @@ class Queue implements \Countable
27
27
private $ limit ;
28
28
private $ handler ;
29
29
30
+ /** @var int<0,max> */
30
31
private $ pending = 0 ;
32
+
33
+ /** @var array<int,\Closure():void> */
31
34
private $ queue = array ();
32
35
33
36
/**
@@ -373,24 +376,42 @@ public function __invoke()
373
376
$ id = key ($ queue );
374
377
assert (is_int ($ id ));
375
378
376
- $ deferred = new Deferred (function ($ _ , $ reject ) use (&$ queue , $ id , &$ deferred ) {
379
+ /** @var ?PromiseInterface<T> $pending */
380
+ $ pending = null ;
381
+
382
+ $ deferred = new Deferred (function ($ _ , $ reject ) use (&$ queue , $ id , &$ pending ) {
377
383
// forward cancellation to pending operation if it is currently executing
378
- if (isset ( $ deferred -> pending ) && $ deferred -> pending instanceof PromiseInterface && \method_exists ($ deferred -> pending , 'cancel ' )) {
379
- $ deferred -> pending ->cancel ();
384
+ if ($ pending instanceof PromiseInterface && \method_exists ($ pending , 'cancel ' )) {
385
+ $ pending ->cancel ();
380
386
}
381
- unset( $ deferred -> pending ) ;
387
+ $ pending = null ;
382
388
383
- if (isset ($ deferred -> args )) {
389
+ if (isset ($ queue [ $ id ] )) {
384
390
// queued promise cancelled before its handler is invoked
385
391
// remove from queue and reject explicitly
386
- unset($ queue [$ id ], $ deferred -> args );
392
+ unset($ queue [$ id ]);
387
393
$ reject (new \RuntimeException ('Cancelled queued job before processing started ' ));
388
394
}
389
395
});
390
396
391
397
// queue job to process if number of pending jobs is below concurrency limit again
392
- $ deferred ->args = func_get_args ();
393
- $ queue [$ id ] = $ deferred ;
398
+ $ handler = $ this ->handler ; // PHP 5.4+
399
+ $ args = func_get_args ();
400
+ $ that = $ this ; // PHP 5.4+
401
+ $ queue [$ id ] = function () use ($ handler , $ args , $ deferred , &$ pending , $ that ) {
402
+ $ pending = \call_user_func_array ($ handler , $ args );
403
+
404
+ $ that ->await ($ pending )->then (
405
+ function ($ result ) use ($ deferred , &$ pending ) {
406
+ $ pending = null ;
407
+ $ deferred ->resolve ($ result );
408
+ },
409
+ function ($ e ) use ($ deferred , &$ pending ) {
410
+ $ pending = null ;
411
+ $ deferred ->reject ($ e );
412
+ }
413
+ );
414
+ };
394
415
395
416
return $ deferred ->promise ();
396
417
}
@@ -407,7 +428,7 @@ public function count()
407
428
*/
408
429
public function await (PromiseInterface $ promise )
409
430
{
410
- $ that = $ this ;
431
+ $ that = $ this ; // PHP 5.4+
411
432
412
433
return $ promise ->then (function ($ result ) use ($ that ) {
413
434
$ that ->processQueue ();
@@ -430,28 +451,15 @@ public function processQueue()
430
451
return ;
431
452
}
432
453
433
- $ deferred = reset ($ this ->queue );
434
- assert ($ deferred instanceof Deferred );
454
+ $ next = reset ($ this ->queue );
455
+ assert ($ next instanceof \Closure );
435
456
unset($ this ->queue [key ($ this ->queue )]);
436
457
437
458
// once number of pending jobs is below concurrency limit again:
438
459
// await this situation, invoke handler and await its resolution before invoking next queued job
439
460
++$ this ->pending ;
440
461
441
- $ promise = call_user_func_array ($ this ->handler , $ deferred ->args );
442
- $ deferred ->pending = $ promise ;
443
- unset($ deferred ->args );
444
-
445
462
// invoke handler and await its resolution before invoking next queued job
446
- $ this ->await ($ promise )->then (
447
- function ($ result ) use ($ deferred ) {
448
- unset($ deferred ->pending );
449
- $ deferred ->resolve ($ result );
450
- },
451
- function ($ e ) use ($ deferred ) {
452
- unset($ deferred ->pending );
453
- $ deferred ->reject ($ e );
454
- }
455
- );
463
+ $ next ();
456
464
}
457
465
}
0 commit comments