diff --git a/lib/Loop/Internal/TimerQueue.php b/lib/Loop/Internal/TimerQueue.php index 243bb20..ea328bb 100644 --- a/lib/Loop/Internal/TimerQueue.php +++ b/lib/Loop/Internal/TimerQueue.php @@ -50,7 +50,7 @@ final class TimerQueue } /** - * Removes the given watcher from the queue. Time complexity: O(1). + * Removes the given watcher from the queue. Time complexity: O(log(n)). * * @param Watcher $watcher * @@ -78,7 +78,7 @@ final class TimerQueue public function extract(int $now) { if (empty($this->data)) { - throw new \Error('No data left in the heap.'); + return null; } $data = $this->data[0]; @@ -92,6 +92,16 @@ final class TimerQueue return $data->watcher; } + /** + * Returns the expiration time value at the top of the heap. Time complexity: O(1). + * + * @return int|null Expiration time of the watcher at the top of the heap or null if the heap is empty. + */ + public function peek() + { + return isset($this->data[0]) ? $this->data[0]->expiration : -1; + } + /** * @param int $node Remove the given node and then rebuild the data array from that node downward. * @@ -130,28 +140,4 @@ final class TimerQueue $node = $swap; } } - - /** - * Returns the expiration time value at the top of the heap. Time complexity: O(1). - * - * @return int Expiration time of the watcher at the top of the heap. - */ - public function peek(): int - { - if (empty($this->data)) { - throw new \Error('No data in the heap.'); - } - - return $this->data[0]->expiration; - } - - /** - * Determines if the heap is empty. - * - * @return bool - */ - public function isEmpty(): bool - { - return empty($this->data); - } } diff --git a/lib/Loop/NativeDriver.php b/lib/Loop/NativeDriver.php index 38d65da..9061bbb 100644 --- a/lib/Loop/NativeDriver.php +++ b/lib/Loop/NativeDriver.php @@ -100,15 +100,11 @@ class NativeDriver extends Driver $scheduleQueue = []; try { - while (!$this->timerQueue->isEmpty()) { - $watcher = $this->timerQueue->extract($this->now()); - - if ($watcher === null) { // Timer at top of queue has not expired. - break; - } + $now = $this->now(); + while ($watcher = $this->timerQueue->extract($now)) { if ($watcher->type & Watcher::REPEAT) { - $expiration = $this->now() + $watcher->value; + $expiration = $now + $watcher->value; $scheduleQueue[] = [$watcher, $expiration]; } else { $this->cancel($watcher->id); @@ -256,19 +252,15 @@ class NativeDriver extends Driver */ private function getTimeout(): int { - if (!$this->timerQueue->isEmpty()) { - $expiration = $this->timerQueue->peek(); + $expiration = $this->timerQueue->peek(); - $expiration -= getCurrentTime() - $this->nowOffset; - - if ($expiration < 0) { - return 0; - } - - return $expiration; + if ($expiration === null) { + return -1; } - return -1; + $expiration -= getCurrentTime() - $this->nowOffset; + + return $expiration > 0 ? $expiration : 0; } /**