mirror of
https://github.com/danog/amp.git
synced 2024-11-26 20:15:00 +01:00
Fix timers with interval = 0 in NativeDriver
This commit is contained in:
parent
5bca41ade4
commit
dbc853c3f1
@ -69,43 +69,51 @@ class NativeDriver extends Driver {
|
||||
);
|
||||
|
||||
if (!empty($this->timerExpires)) {
|
||||
while (!$this->timerQueue->isEmpty()) {
|
||||
list($watcher, $expiration) = $this->timerQueue->top();
|
||||
$scheduleQueue = [];
|
||||
|
||||
$id = $watcher->id;
|
||||
try {
|
||||
while (!$this->timerQueue->isEmpty()) {
|
||||
list($watcher, $expiration) = $this->timerQueue->top();
|
||||
|
||||
if (!isset($this->timerExpires[$id]) || $expiration !== $this->timerExpires[$id]) {
|
||||
$this->timerQueue->extract(); // Timer was removed from queue.
|
||||
continue;
|
||||
}
|
||||
$id = $watcher->id;
|
||||
|
||||
if ($this->timerExpires[$id] > $this->now) { // Timer at top of queue has not expired.
|
||||
break;
|
||||
}
|
||||
|
||||
$this->timerQueue->extract();
|
||||
|
||||
if ($watcher->type & Watcher::REPEAT) {
|
||||
$expiration = $this->now + $watcher->value;
|
||||
$this->timerExpires[$watcher->id] = $expiration;
|
||||
$this->timerQueue->insert([$watcher, $expiration], -$expiration);
|
||||
} else {
|
||||
$this->cancel($id);
|
||||
}
|
||||
|
||||
try {
|
||||
// Execute the timer.
|
||||
$result = ($watcher->callback)($id, $watcher->data);
|
||||
|
||||
if ($result instanceof \Generator) {
|
||||
$result = new Coroutine($result);
|
||||
if (!isset($this->timerExpires[$id]) || $expiration !== $this->timerExpires[$id]) {
|
||||
$this->timerQueue->extract(); // Timer was removed from queue.
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($result instanceof Promise || $result instanceof ReactPromise) {
|
||||
rethrow($result);
|
||||
if ($this->timerExpires[$id] > $this->now) { // Timer at top of queue has not expired.
|
||||
break;
|
||||
}
|
||||
} catch (\Throwable $exception) {
|
||||
$this->error($exception);
|
||||
|
||||
$this->timerQueue->extract();
|
||||
|
||||
if ($watcher->type & Watcher::REPEAT) {
|
||||
$expiration = $this->now + $watcher->value;
|
||||
$this->timerExpires[$watcher->id] = $expiration;
|
||||
$scheduleQueue[] = [$watcher, $expiration];
|
||||
} else {
|
||||
$this->cancel($id);
|
||||
}
|
||||
|
||||
try {
|
||||
// Execute the timer.
|
||||
$result = ($watcher->callback)($id, $watcher->data);
|
||||
|
||||
if ($result instanceof \Generator) {
|
||||
$result = new Coroutine($result);
|
||||
}
|
||||
|
||||
if ($result instanceof Promise || $result instanceof ReactPromise) {
|
||||
rethrow($result);
|
||||
}
|
||||
} catch (\Throwable $exception) {
|
||||
$this->error($exception);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
foreach ($scheduleQueue as $item) {
|
||||
$this->timerQueue->insert($item, -$item[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1433,4 +1433,23 @@ abstract class DriverTest extends TestCase {
|
||||
});
|
||||
$this->loop->run();
|
||||
}
|
||||
|
||||
public function testShortTimerDoesNotBlockOtherTimers() {
|
||||
$this->loop->repeat(0, function () {
|
||||
static $i = 0;
|
||||
|
||||
if (++$i === 5) {
|
||||
$this->fail("Loop continues with repeat watcher");
|
||||
}
|
||||
|
||||
\usleep(2000);
|
||||
});
|
||||
|
||||
$this->loop->delay(2, function () {
|
||||
$this->assertTrue(true);
|
||||
$this->loop->stop();
|
||||
});
|
||||
|
||||
$this->loop->run();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user