1
0
mirror of https://github.com/danog/amp.git synced 2024-12-12 09:29:45 +01:00

Merge branch 'master' into v3

# Conflicts:
#	lib/Loop/Internal/TimerQueue.php
#	lib/Loop/Internal/TimerQueueEntry.php
This commit is contained in:
Aaron Piotrowski 2020-11-14 10:52:36 -06:00
commit 31adf876b6
No known key found for this signature in database
GPG Key ID: ADD1EF783EDE9EEB
2 changed files with 20 additions and 53 deletions

View File

@ -9,7 +9,7 @@ use Amp\Loop\Watcher;
*/ */
final class TimerQueue final class TimerQueue
{ {
/** @var TimerQueueEntry[] */ /** @var Watcher[] */
private array $data = []; private array $data = [];
/** @var int[] */ /** @var int[] */
@ -24,13 +24,7 @@ final class TimerQueue
{ {
$entry = $this->data[$node]; $entry = $this->data[$node];
while ($node !== 0 && $entry->expiration < $this->data[$parent = ($node - 1) >> 1]->expiration) { while ($node !== 0 && $entry->expiration < $this->data[$parent = ($node - 1) >> 1]->expiration) {
$temp = $this->data[$parent]; $this->swap($node, $parent);
$this->data[$node] = $temp;
$this->pointers[$temp->watcher->id] = $node;
$this->data[$parent] = $entry;
$this->pointers[$entry->watcher->id] = $parent;
$node = $parent; $node = $parent;
} }
} }
@ -56,19 +50,22 @@ final class TimerQueue
break; break;
} }
$left = $this->data[$node]; $this->swap($node, $swap);
$right = $this->data[$swap];
$this->data[$node] = $right;
$this->pointers[$right->watcher->id] = $node;
$this->data[$swap] = $left;
$this->pointers[$left->watcher->id] = $swap;
$node = $swap; $node = $swap;
} }
} }
private function swap(int $left, int $right): void
{
$temp = $this->data[$left];
$this->data[$left] = $this->data[$right];
$this->pointers[$this->data[$right]->id] = $left;
$this->data[$right] = $temp;
$this->pointers[$temp->id] = $right;
}
/** /**
* Inserts the watcher into the queue. Time complexity: O(log(n)). * Inserts the watcher into the queue. Time complexity: O(log(n)).
* *
@ -83,10 +80,8 @@ final class TimerQueue
\assert($watcher->expiration !== null); \assert($watcher->expiration !== null);
\assert(!isset($this->pointers[$watcher->id])); \assert(!isset($this->pointers[$watcher->id]));
$entry = new TimerQueueEntry($watcher, $watcher->expiration);
$node = \count($this->data); $node = \count($this->data);
$this->data[$node] = $entry; $this->data[$node] = $watcher;
$this->pointers[$watcher->id] = $node; $this->pointers[$watcher->id] = $node;
$this->heapifyUp($node); $this->heapifyUp($node);
@ -128,15 +123,15 @@ final class TimerQueue
return null; return null;
} }
$data = $this->data[0]; $watcher = $this->data[0];
if ($data->expiration > $now) { if ($watcher->expiration > $now) {
return null; return null;
} }
$this->removeAndRebuild(0); $this->removeAndRebuild(0);
return $data->watcher; return $watcher;
} }
/** /**
@ -157,9 +152,9 @@ final class TimerQueue
private function removeAndRebuild(int $node): void private function removeAndRebuild(int $node): void
{ {
$length = \count($this->data) - 1; $length = \count($this->data) - 1;
$id = $this->data[$node]->watcher->id; $id = $this->data[$node]->id;
$left = $this->data[$node] = $this->data[$length]; $left = $this->data[$node] = $this->data[$length];
$this->pointers[$left->watcher->id] = $node; $this->pointers[$left->id] = $node;
unset($this->data[$length], $this->pointers[$id]); unset($this->data[$length], $this->pointers[$id]);
if ($node < $length) { // don't need to do anything if we removed the last element if ($node < $length) { // don't need to do anything if we removed the last element

View File

@ -1,28 +0,0 @@
<?php
namespace Amp\Loop\Internal;
use Amp\Loop\Watcher;
use Amp\Struct;
/**
* @internal
*/
final class TimerQueueEntry
{
use Struct;
public Watcher $watcher;
public int $expiration;
/**
* @param Watcher $watcher
* @param int $expiration
*/
public function __construct(Watcher $watcher, int $expiration)
{
$this->watcher = $watcher;
$this->expiration = $expiration;
}
}