mirror of
https://github.com/danog/amp.git
synced 2024-12-03 09:57:51 +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";
|
||||
|
||||
/** @var \Closure(CancelledException)[] */
|
||||
/** @var array<string, \Closure(CancelledException): void> */
|
||||
private array $callbacks = [];
|
||||
|
||||
private ?CancelledException $exception = null;
|
||||
|
||||
public function __construct(Cancellation ...$cancellations)
|
||||
{
|
||||
foreach ($cancellations as $cancellation) {
|
||||
$id = $cancellation->subscribe(function (CancelledException $exception): void {
|
||||
$this->exception = $exception;
|
||||
$thatException = &$this->exception;
|
||||
$thatCallbacks = &$this->callbacks;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
$this->callbacks = [];
|
||||
$thatCallbacks = [];
|
||||
});
|
||||
|
||||
$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