Skip to content

Commit

Permalink
Implement monotonic timer using PHP 7.3's hrtime()
Browse files Browse the repository at this point in the history
  • Loading branch information
kelunik committed Dec 10, 2018
1 parent 5889f4e commit 5622edb
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 11 deletions.
15 changes: 15 additions & 0 deletions lib/Internal/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,18 @@ function createTypeError(array $expected, $given): \TypeError

return new \TypeError("{$expectedType}; {$givenType} given");
}

/**
* Returns the current time relative to an arbitrary point in time.
*
* @return int Time in milliseconds.
*/
function getCurrentTime(): int
{
if (\PHP_VERSION_ID >= 70300) {
list($seconds, $nanoseconds) = \hrtime(false);
return $seconds * 1000 + $nanoseconds / 1000000;
}

return (int) (\microtime(true) * 1000);
}
7 changes: 4 additions & 3 deletions lib/Loop/EvDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Amp\Coroutine;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
use function Amp\Internal\getCurrentTime;
use function Amp\Promise\rethrow;

class EvDriver extends Driver
Expand Down Expand Up @@ -36,13 +37,13 @@ class EvDriver extends Driver
/** @var bool */
private $nowUpdateNeeded = false;

/** @var int Loop time offset from microtime() */
/** @var int Loop time offset */
private $nowOffset;

public function __construct()
{
$this->handle = new \EvLoop;
$this->nowOffset = (int) (\microtime(true) * self::MILLISEC_PER_SEC);
$this->nowOffset = getCurrentTime();
$this->now = \random_int(0, $this->nowOffset);
$this->nowOffset -= $this->now;

Expand Down Expand Up @@ -203,7 +204,7 @@ public function stop()
public function now(): int
{
if ($this->nowUpdateNeeded) {
$this->now = (int) (\microtime(true) * self::MILLISEC_PER_SEC) - $this->nowOffset;
$this->now = getCurrentTime() - $this->nowOffset;
$this->nowUpdateNeeded = false;
}

Expand Down
9 changes: 5 additions & 4 deletions lib/Loop/EventDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Amp\Coroutine;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
use function Amp\Internal\getCurrentTime;
use function Amp\Promise\rethrow;

class EventDriver extends Driver
Expand Down Expand Up @@ -36,13 +37,13 @@ class EventDriver extends Driver
/** @var int Internal timestamp for now. */
private $now;

/** @var int Loop time offset from microtime() */
/** @var int Loop time offset */
private $nowOffset;

public function __construct()
{
$this->handle = new \EventBase;
$this->nowOffset = (int) (\microtime(true) * self::MILLISEC_PER_SEC);
$this->nowOffset = getCurrentTime();
$this->now = \random_int(0, $this->nowOffset);
$this->nowOffset -= $this->now;

Expand Down Expand Up @@ -205,7 +206,7 @@ public function stop()
public function now(): int
{
if ($this->nowUpdateNeeded) {
$this->now = (int) (\microtime(true) * self::MILLISEC_PER_SEC) - $this->nowOffset;
$this->now = getCurrentTime() - $this->nowOffset;
$this->nowUpdateNeeded = false;
}

Expand Down Expand Up @@ -234,7 +235,7 @@ protected function dispatch(bool $blocking)
*/
protected function activate(array $watchers)
{
$now = (int) (\microtime(true) * self::MILLISEC_PER_SEC) - $this->nowOffset;
$now = getCurrentTime() - $this->nowOffset;

foreach ($watchers as $watcher) {
if (!isset($this->events[$id = $watcher->id])) {
Expand Down
9 changes: 5 additions & 4 deletions lib/Loop/NativeDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Amp\Coroutine;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
use function Amp\Internal\getCurrentTime;
use function Amp\Promise\rethrow;

class NativeDriver extends Driver
Expand Down Expand Up @@ -36,7 +37,7 @@ class NativeDriver extends Driver
/** @var int Internal timestamp for now. */
private $now;

/** @var int Loop time offset from microtime() */
/** @var int Loop time offset */
private $nowOffset;

/** @var bool */
Expand All @@ -46,7 +47,7 @@ public function __construct()
{
$this->timerQueue = new \SplPriorityQueue();
$this->signalHandling = \extension_loaded("pcntl");
$this->nowOffset = (int) (\microtime(true) * self::MILLISEC_PER_SEC);
$this->nowOffset = getCurrentTime();
$this->now = \random_int(0, $this->nowOffset);
$this->nowOffset -= $this->now;
}
Expand All @@ -71,7 +72,7 @@ public function onSignal(int $signo, callable $callback, $data = null): string
public function now(): int
{
if ($this->nowUpdateNeeded) {
$this->now = (int) (\microtime(true) * self::MILLISEC_PER_SEC) - $this->nowOffset;
$this->now = getCurrentTime() - $this->nowOffset;
$this->nowUpdateNeeded = false;
}

Expand Down Expand Up @@ -275,7 +276,7 @@ private function getTimeout()
continue;
}

$expiration -= (int) (\microtime(true) * self::MILLISEC_PER_SEC);
$expiration -= getCurrentTime();

if ($expiration < 0) {
return 0;
Expand Down

0 comments on commit 5622edb

Please sign in to comment.