mirror of
https://github.com/danog/amp.git
synced 2024-12-12 09:29:45 +01:00
Fixed memory leak in CombinedCancellationToken (#384)
Co-authored-by: Artur Khasanov <ah@self.team>
This commit is contained in:
parent
d05b7d56e9
commit
f38e756a3d
@ -11,22 +11,28 @@ final class CompositeCancellation implements Cancellation
|
|||||||
|
|
||||||
private string $nextId = "a";
|
private string $nextId = "a";
|
||||||
|
|
||||||
/** @var \Closure(CancelledException)[] */
|
/** @var array<string, \Closure(CancelledException): void> */
|
||||||
private array $callbacks = [];
|
private array $callbacks = [];
|
||||||
|
|
||||||
private ?CancelledException $exception = null;
|
private ?CancelledException $exception = null;
|
||||||
|
|
||||||
public function __construct(Cancellation ...$cancellations)
|
public function __construct(Cancellation ...$cancellations)
|
||||||
{
|
{
|
||||||
foreach ($cancellations as $cancellation) {
|
$thatException = &$this->exception;
|
||||||
$id = $cancellation->subscribe(function (CancelledException $exception): void {
|
$thatCallbacks = &$this->callbacks;
|
||||||
$this->exception = $exception;
|
|
||||||
|
|
||||||
foreach ($this->callbacks as $callback) {
|
foreach ($cancellations as $cancellation) {
|
||||||
|
$id = $cancellation->subscribe(static function (CancelledException $exception) use (
|
||||||
|
&$thatException,
|
||||||
|
&$thatCallbacks
|
||||||
|
): void {
|
||||||
|
$thatException = $exception;
|
||||||
|
|
||||||
|
foreach ($thatCallbacks as $callback) {
|
||||||
EventLoop::queue($callback, $exception);
|
EventLoop::queue($callback, $exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->callbacks = [];
|
$thatCallbacks = [];
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->cancellations[] = [$cancellation, $id];
|
$this->cancellations[] = [$cancellation, $id];
|
||||||
|
41
test/Cancellation/CompositeCancellationTest.php
Normal file
41
test/Cancellation/CompositeCancellationTest.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Cancellation;
|
||||||
|
|
||||||
|
use Amp\CompositeCancellation;
|
||||||
|
use Amp\DeferredCancellation;
|
||||||
|
use Amp\PHPUnit\AsyncTestCase;
|
||||||
|
use function Amp\delay;
|
||||||
|
|
||||||
|
class CompositeCancellationTest extends AsyncTestCase
|
||||||
|
{
|
||||||
|
private const LOOP_COUNT = 20;
|
||||||
|
private const TOKENS_COUNT = 1000;
|
||||||
|
|
||||||
|
public function testBenchmark(): void
|
||||||
|
{
|
||||||
|
$firstMemoryMeasure = 0;
|
||||||
|
|
||||||
|
for ($i = 0; $i < self::LOOP_COUNT; $i++) {
|
||||||
|
$tokens = [];
|
||||||
|
for ($j = 0; $j < self::TOKENS_COUNT; $j++) {
|
||||||
|
$tokens[] = (new DeferredCancellation())->getCancellation();
|
||||||
|
}
|
||||||
|
$combinedToken = new CompositeCancellation(...$tokens);
|
||||||
|
|
||||||
|
if (!$firstMemoryMeasure && $i > self::LOOP_COUNT / 2) {
|
||||||
|
// Warmup and store first memory usage after 50% of iterations
|
||||||
|
$firstMemoryMeasure = \memory_get_usage(true);
|
||||||
|
}
|
||||||
|
// Remove tokens from memory
|
||||||
|
unset($combinedToken);
|
||||||
|
|
||||||
|
delay(0.001); // Tick loop to allow resources to be freed.
|
||||||
|
|
||||||
|
// Asserts
|
||||||
|
if ($firstMemoryMeasure > 0) {
|
||||||
|
self::assertEquals($firstMemoryMeasure, \memory_get_usage(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user