1
0
mirror of https://github.com/danog/loop.git synced 2024-11-30 04:19:04 +01:00

Fix memory leak

This commit is contained in:
Daniil Gentili 2023-01-22 10:05:04 +01:00
parent 8309d5be1d
commit 59354bb12d
7 changed files with 41 additions and 45 deletions

View File

@ -52,7 +52,6 @@ class MyLoop extends Loop
*/ */
protected function startedLoop(): void protected function startedLoop(): void
{ {
parent::startedLoop();
echo "Started loop $this!".PHP_EOL; echo "Started loop $this!".PHP_EOL;
} }
/** /**
@ -61,7 +60,6 @@ class MyLoop extends Loop
*/ */
protected function exitedLoop(): void protected function exitedLoop(): void
{ {
parent::exitedLoop();
echo "Exited loop $this!".PHP_EOL; echo "Exited loop $this!".PHP_EOL;
} }
// End of logging methods // End of logging methods

View File

@ -43,7 +43,6 @@ class MyLoop extends ResumableLoop
*/ */
protected function startedLoop(): void protected function startedLoop(): void
{ {
parent::startedLoop();
echo "Started loop $this!".PHP_EOL; echo "Started loop $this!".PHP_EOL;
} }
/** /**
@ -52,7 +51,6 @@ class MyLoop extends ResumableLoop
*/ */
protected function exitedLoop(): void protected function exitedLoop(): void
{ {
parent::exitedLoop();
echo "Exited loop $this!".PHP_EOL; echo "Exited loop $this!".PHP_EOL;
} }
// End of logging methods // End of logging methods

View File

@ -18,18 +18,6 @@ use function Amp\async;
/** /**
* Generic loop, runs single callable. * Generic loop, runs single callable.
* *
* The return value of the callable can be:
* * A number - the loop will be paused for the specified number of seconds
* * GenericLoop::STOP - The loop will stop
* * GenericLoop::PAUSE - The loop will pause forever (or until loop is `resumed()`
* from outside the loop)
* * GenericLoop::CONTINUE - Return this if you want to rerun the loop immediately
*
* If the callable does not return anything,
* the loop will behave is if GenericLoop::PAUSE was returned.
*
* The loop can be stopped from the outside by signaling `true`.
*
* @psalm-type TCallableReturn=int|null|Future<int|null> * @psalm-type TCallableReturn=int|null|Future<int|null>
* *
* @author Daniil Gentili <daniil@daniil.it> * @author Daniil Gentili <daniil@daniil.it>
@ -57,6 +45,18 @@ class GenericLoop extends ResumableSignalLoop
/** /**
* Constructor. * Constructor.
* *
* The return value of the callable can be:
* * A number - the loop will be paused for the specified number of seconds
* * GenericLoop::STOP - The loop will stop
* * GenericLoop::PAUSE - The loop will pause forever (or until loop is `resumed()`
* from outside the loop)
* * GenericLoop::CONTINUE - Return this if you want to rerun the loop immediately
*
* If the callable does not return anything,
* the loop will behave is if GenericLoop::PAUSE was returned.
*
* The loop can be stopped from the outside by signaling `true`.
*
* If possible, the callable will be bound to the current instance of the loop. * If possible, the callable will be bound to the current instance of the loop.
* *
* @param callable():TCallableReturn $callable Callable to run * @param callable():TCallableReturn $callable Callable to run

View File

@ -9,7 +9,8 @@
namespace danog\Loop\Traits; namespace danog\Loop\Traits;
use function Amp\async; use danog\Loop\Interfaces\LoopInterface;
use Revolt\EventLoop;
/** /**
* Loop helper trait. * Loop helper trait.
@ -17,43 +18,51 @@ use function Amp\async;
* Wraps the asynchronous generator methods with asynchronous promise-based methods * Wraps the asynchronous generator methods with asynchronous promise-based methods
* *
* @author Daniil Gentili <daniil@daniil.it> * @author Daniil Gentili <daniil@daniil.it>
*
* @psalm-require-implements LoopInterface
*/ */
trait Loop trait Loop
{ {
/** /**
* Whether the loop was started. * Whether the loop was started.
*
* @var bool
*/ */
private $started = false; private bool $started = false;
/** /**
* Start the loop. * Start the loop.
* *
* Returns false if the loop is already running. * Returns false if the loop is already running.
*
*/ */
public function start(): bool public function start(): bool
{ {
if ($this->started) { if ($this->started) {
return false; return false;
} }
async(function (): void { EventLoop::queue(function (): void {
$this->startedLoop(); $this->startedLoopInternal();
try { try {
$this->loop(); $this->loop();
} finally { } finally {
$this->exitedLoop(); $this->exitedLoopInternal();
} }
}); });
return true; return true;
} }
private function exitedLoopInternal(): void
{
$this->started = false;
$this->exitedLoop();
}
private function startedLoopInternal(): void
{
$this->started = true;
$this->startedLoop();
}
/** /**
* Signal that loop has exIited. * Signal that loop has exited.
* *
*/ */
protected function exitedLoop(): void protected function exitedLoop(): void
{ {
$this->started = false;
} }
/** /**
* Signal that loop has started. * Signal that loop has started.
@ -61,7 +70,6 @@ trait Loop
*/ */
protected function startedLoop(): void protected function startedLoop(): void
{ {
$this->started = true;
} }
/** /**
* Check whether loop is running. * Check whether loop is running.

View File

@ -22,7 +22,7 @@ use Revolt\EventLoop;
trait ResumableLoop trait ResumableLoop
{ {
use Loop { use Loop {
exitedLoop as private parentExitedLoop; exitedLoopInternal as private parentExitedLoop;
} }
/** /**
* Resume deferred. * Resume deferred.
@ -66,7 +66,7 @@ trait ResumableLoop
/** @var DeferredFuture<null> */ /** @var DeferredFuture<null> */
$this->pause = new DeferredFuture(); $this->pause = new DeferredFuture();
if ($pause) { if ($pause) {
EventLoop::defer(function () use ($pause): void { $pause->complete(); }); EventLoop::queue($pause->complete(...));
} }
/** @var DeferredFuture<null> */ /** @var DeferredFuture<null> */
@ -95,7 +95,7 @@ trait ResumableLoop
*/ */
public function resumeDefer(): Future public function resumeDefer(): Future
{ {
EventLoop::defer($this->resumeInternal(...)); EventLoop::queue($this->resumeInternal(...));
if (!$this->pause) { if (!$this->pause) {
/** @var DeferredFuture<null> */ /** @var DeferredFuture<null> */
$this->pause = new DeferredFuture; $this->pause = new DeferredFuture;
@ -143,12 +143,9 @@ trait ResumableLoop
/** /**
* Signal that loop has exited. * Signal that loop has exited.
*/ */
protected function exitedLoop(): void private function exitedLoopInternal(): void
{ {
$this->resumeInternal();
$this->parentExitedLoop(); $this->parentExitedLoop();
if ($this->resumeTimer) {
EventLoop::cancel($this->resumeTimer);
$this->resumeTimer = null;
}
} }
} }

View File

@ -5,6 +5,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config" xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
errorBaseline="psalm-baseline.xml"
> >
<projectFiles> <projectFiles>
<directory name="lib" /> <directory name="lib" />

View File

@ -13,34 +13,28 @@ trait Logging
{ {
/** /**
* Check whether the loop started. * Check whether the loop started.
*
* @var int
*/ */
private $startCounter = 0; private int $startCounter = 0;
/** /**
* Check whether the loop ended. * Check whether the loop ended.
*
* @var int
*/ */
private $endCounter = 0; private int $endCounter = 0;
/** /**
* Signal that loop started. * Signal that loop started.
* *
*/ */
protected function startedLoop(): void final protected function startedLoop(): void
{ {
$this->startCounter++; $this->startCounter++;
parent::startedLoop();
} }
/** /**
* Signal that loop ended. * Signal that loop ended.
* *
*/ */
protected function exitedLoop(): void final protected function exitedLoop(): void
{ {
$this->endCounter++; $this->endCounter++;
parent::exitedLoop();
} }
/** /**