Skip to content

Commit 170fb93

Browse files
authored
Merge pull request #34 from clue-labs/garbage
Improve memory consumption by cleaning up garbage references to pending promise without canceller
2 parents c217811 + 28dc64e commit 170fb93

File tree

3 files changed

+45
-4
lines changed

3 files changed

+45
-4
lines changed

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"require": {
2121
"php": ">=5.3",
2222
"react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3.5",
23-
"react/promise": "^2.6.0 || ^1.2.1"
23+
"react/promise": "^2.7.0 || ^1.2.1"
2424
},
2525
"require-dev": {
2626
"phpunit/phpunit": "^6.4 || ^5.7 || ^4.8.35"

src/functions.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ function timeout(PromiseInterface $promise, $time, LoopInterface $loop)
2323

2424
return new Promise(function ($resolve, $reject) use ($loop, $time, $promise) {
2525
$timer = null;
26-
$promise->then(function ($v) use (&$timer, $loop, $resolve) {
26+
$promise = $promise->then(function ($v) use (&$timer, $loop, $resolve) {
2727
if ($timer) {
2828
$loop->cancelTimer($timer);
2929
}

tests/FunctionTimeoutTest.php

+43-2
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,13 @@ public function testPendingWillRejectOnTimeout()
7171
$this->expectPromiseRejected($promise);
7272
}
7373

74-
public function testPendingCancellableWillBeCancelledOnTimeout()
74+
public function testPendingCancellableWillBeCancelledThroughFollowerOnTimeout()
7575
{
76+
$cancellable = $this->getMockBuilder('React\Promise\CancellablePromiseInterface')->getMock();
77+
$cancellable->expects($this->once())->method('cancel');
78+
7679
$promise = $this->getMockBuilder('React\Promise\CancellablePromiseInterface')->getMock();
77-
$promise->expects($this->once())->method('cancel');
80+
$promise->expects($this->once())->method('then')->willReturn($cancellable);
7881

7982
Timer\timeout($promise, 0.01, $this->loop);
8083

@@ -223,6 +226,44 @@ public function testWaitingForPromiseToTimeoutDoesNotLeaveGarbageCycles()
223226
$this->assertEquals(0, gc_collect_cycles());
224227
}
225228

229+
public function testWaitingForPromiseToTimeoutWithoutCancellerDoesNotLeaveGarbageCycles()
230+
{
231+
if (class_exists('React\Promise\When')) {
232+
$this->markTestSkipped('Not supported on legacy Promise v1 API');
233+
}
234+
235+
gc_collect_cycles();
236+
237+
$promise = new \React\Promise\Promise(function () { });
238+
239+
$promise = Timer\timeout($promise, 0.01, $this->loop);
240+
241+
$this->loop->run();
242+
unset($promise);
243+
244+
$this->assertEquals(0, gc_collect_cycles());
245+
}
246+
247+
public function testWaitingForPromiseToTimeoutWithNoOpCancellerDoesNotLeaveGarbageCycles()
248+
{
249+
if (class_exists('React\Promise\When')) {
250+
$this->markTestSkipped('Not supported on legacy Promise v1 API');
251+
}
252+
253+
gc_collect_cycles();
254+
255+
$promise = new \React\Promise\Promise(function () { }, function () {
256+
// no-op
257+
});
258+
259+
$promise = Timer\timeout($promise, 0.01, $this->loop);
260+
261+
$this->loop->run();
262+
unset($promise);
263+
264+
$this->assertEquals(0, gc_collect_cycles());
265+
}
266+
226267
public function testCancellingPromiseDoesNotLeaveGarbageCycles()
227268
{
228269
if (class_exists('React\Promise\When')) {

0 commit comments

Comments
 (0)