mirror of
https://github.com/danog/amp.git
synced 2024-12-11 00:49:48 +01:00
Only create deferred for backpressure if necessary
This commit is contained in:
parent
c45cd5a3a9
commit
a726db92a5
@ -23,7 +23,6 @@ Loop::run(function () {
|
|||||||
|
|
||||||
$iterator = $emitter->iterate();
|
$iterator = $emitter->iterate();
|
||||||
yield $iterator->advance();
|
yield $iterator->advance();
|
||||||
yield $iterator->advance();
|
|
||||||
yield new Amp\Delayed(0);
|
yield new Amp\Delayed(0);
|
||||||
|
|
||||||
unset($emitter, $iterator);
|
unset($emitter, $iterator);
|
||||||
|
@ -28,7 +28,10 @@ trait Producer
|
|||||||
private $backPressure = [];
|
private $backPressure = [];
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
private $position = -1;
|
private $consumePosition = -1;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private $emitPosition = -1;
|
||||||
|
|
||||||
/** @var \Amp\Deferred|null */
|
/** @var \Amp\Deferred|null */
|
||||||
private $waiting;
|
private $waiting;
|
||||||
@ -45,20 +48,15 @@ trait Producer
|
|||||||
throw new \Error("The prior promise returned must resolve before invoking this method again");
|
throw new \Error("The prior promise returned must resolve before invoking this method again");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->backPressure[$this->position])) {
|
unset($this->values[$this->consumePosition]);
|
||||||
$future = $this->backPressure[$this->position];
|
|
||||||
unset($this->values[$this->position], $this->backPressure[$this->position]);
|
|
||||||
$future->resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
++$this->position;
|
$position = ++$this->consumePosition;
|
||||||
|
|
||||||
if (\array_key_exists($this->position, $this->values)) {
|
if (\array_key_exists($position, $this->values)) {
|
||||||
if (isset($this->backPressure[$this->position])) {
|
\assert(isset($this->backPressure[$position]));
|
||||||
$future = $this->backPressure[$this->position];
|
$deferred = $this->backPressure[$position];
|
||||||
unset($this->backPressure[$this->position]);
|
unset($this->backPressure[$position]);
|
||||||
$future->resolve();
|
$deferred->resolve();
|
||||||
}
|
|
||||||
|
|
||||||
return new Success(true);
|
return new Success(true);
|
||||||
}
|
}
|
||||||
@ -68,13 +66,6 @@ trait Producer
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->waiting = new Deferred;
|
$this->waiting = new Deferred;
|
||||||
$this->waiting->promise()->onResolve(function () {
|
|
||||||
if (isset($this->backPressure[$this->position])) {
|
|
||||||
$future = $this->backPressure[$this->position];
|
|
||||||
unset($this->backPressure[$this->position]);
|
|
||||||
$future->resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return $this->waiting->promise();
|
return $this->waiting->promise();
|
||||||
}
|
}
|
||||||
@ -88,16 +79,15 @@ trait Producer
|
|||||||
throw new \Error("The iterator has completed");
|
throw new \Error("The iterator has completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!\array_key_exists($this->position, $this->values)) {
|
if (!\array_key_exists($this->consumePosition, $this->values)) {
|
||||||
throw new \Error("Promise returned from advance() must resolve before calling this method");
|
throw new \Error("Promise returned from advance() must resolve before calling this method");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->values[$this->position];
|
return $this->values[$this->consumePosition];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emits a value from the iterator. The returned promise is resolved with the emitted value once all listeners
|
* Emits a value from the iterator. The returned promise is resolved once the emitted value has been consumed.
|
||||||
* have been invoked.
|
|
||||||
*
|
*
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
*
|
*
|
||||||
@ -137,15 +127,19 @@ trait Producer
|
|||||||
return $deferred->promise();
|
return $deferred->promise();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->values[] = $value;
|
$position = ++$this->emitPosition;
|
||||||
$this->backPressure[] = $pressure = new Deferred;
|
|
||||||
|
$this->values[$position] = $value;
|
||||||
|
|
||||||
if ($this->waiting !== null) {
|
if ($this->waiting !== null) {
|
||||||
$waiting = $this->waiting;
|
$waiting = $this->waiting;
|
||||||
$this->waiting = null;
|
$this->waiting = null;
|
||||||
$waiting->resolve(true);
|
$waiting->resolve(true);
|
||||||
|
return new Success; // Consumer was already waiting for a new value, so back-pressure is unnecessary.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->backPressure[$position] = $pressure = new Deferred;
|
||||||
|
|
||||||
return $pressure->promise();
|
return $pressure->promise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ class ProducerTest extends BaseTest
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->assertGreaterThan(self::TIMEOUT * $emits - 1 /* 1ms grace period */, $time * 1000);
|
$this->assertGreaterThan(self::TIMEOUT * ($emits - 1), $time * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user