Skip to content

Commit

Permalink
Enforce timer interval as minimum time to execution (#319)
Browse files Browse the repository at this point in the history
Co-authored-by: Aaron Piotrowski <aaron@trowski.com>
  • Loading branch information
kelunik and trowski committed Jul 14, 2020
1 parent 0b802a5 commit 05483cd
Show file tree
Hide file tree
Showing 12 changed files with 162 additions and 64 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ install:
- travis/install-ev.sh
- travis/install-event.sh

- if [[ ${TRAVIS_PHP_VERSION:0:3} == "7.0" ]]; then composer remove --dev vimeo/psalm; fi
- if [[ ${TRAVIS_PHP_VERSION:0:3} == "7.0" ]]; then composer remove --dev psalm/phar; fi
- composer update -n --prefer-dist

- mkdir -p coverage/cov coverage/bin
Expand All @@ -45,7 +45,7 @@ script:
- php vendor/bin/phpunit --verbose --group memoryleak
- php vendor/bin/phpunit --verbose --exclude-group memoryleak --coverage-php coverage/cov/main.cov
- PHP_CS_FIXER_IGNORE_ENV=1 php vendor/bin/php-cs-fixer --diff --dry-run -v fix
- if [[ ${TRAVIS_PHP_VERSION:0:3} == "7.0" ]]; then echo "Skipped psalm static analysis"; else vendor/bin/psalm; fi
- if [[ ${TRAVIS_PHP_VERSION:0:3} == "7.0" ]]; then echo "Skipped psalm static analysis"; else vendor/bin/psalm.phar; fi

after_script:
- curl -OL https://github.com/php-coveralls/php-coveralls/releases/download/v1.0.0/coveralls.phar
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"amphp/php-cs-fixer-config": "dev-master",
"react/promise": "^2",
"phpunit/phpunit": "^6.0.9 | ^7",
"vimeo/psalm": "^3.11@dev",
"psalm/phar": "^3.11@dev",
"jetbrains/phpstorm-stubs": "^2019.3"
},
"autoload": {
Expand Down
10 changes: 10 additions & 0 deletions lib/Loop/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ public function delay(int $delay, callable $callback, $data = null): string
$watcher->id = $this->nextId++;
$watcher->callback = $callback;
$watcher->value = $delay;
$watcher->expiration = $this->now() + $delay;
$watcher->data = $data;

$this->watchers[$watcher->id] = $watcher;
Expand Down Expand Up @@ -263,6 +264,7 @@ public function repeat(int $interval, callable $callback, $data = null): string
$watcher->id = $this->nextId++;
$watcher->callback = $callback;
$watcher->value = $interval;
$watcher->expiration = $this->now() + $interval;
$watcher->data = $data;

$this->watchers[$watcher->id] = $watcher;
Expand Down Expand Up @@ -408,6 +410,14 @@ public function enable(string $watcherId)
$this->nextTickQueue[$watcher->id] = $watcher;
break;

case Watcher::REPEAT:
case Watcher::DELAY:
\assert(\is_int($watcher->value));

$watcher->expiration = $this->now() + $watcher->value;
$this->enableQueue[$watcher->id] = $watcher;
break;

default:
$this->enableQueue[$watcher->id] = $watcher;
break;
Expand Down
13 changes: 5 additions & 8 deletions lib/Loop/EvDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ public static function isSupported(): bool
private $signals = [];
/** @var int Internal timestamp for now. */
private $now;
/** @var bool */
private $nowUpdateNeeded = false;
/** @var int Loop time offset */
private $nowOffset;

Expand Down Expand Up @@ -213,10 +211,7 @@ public function stop()
*/
public function now(): int
{
if ($this->nowUpdateNeeded) {
$this->now = getCurrentTime() - $this->nowOffset;
$this->nowUpdateNeeded = false;
}
$this->now = getCurrentTime() - $this->nowOffset;

return $this->now;
}
Expand All @@ -236,7 +231,6 @@ public function getHandle(): \EvLoop
*/
protected function dispatch(bool $blocking)
{
$this->nowUpdateNeeded = true;
$this->handle->run($blocking ? \Ev::RUN_ONCE : \Ev::RUN_ONCE | \Ev::RUN_NOWAIT);
}

Expand All @@ -247,6 +241,9 @@ protected function dispatch(bool $blocking)
*/
protected function activate(array $watchers)
{
$this->handle->nowUpdate();
$now = $this->now();

foreach ($watchers as $watcher) {
if (!isset($this->events[$id = $watcher->id])) {
switch ($watcher->type) {
Expand All @@ -273,7 +270,7 @@ protected function activate(array $watchers)

$interval = $watcher->value / self::MILLISEC_PER_SEC;
$this->events[$id] = $this->handle->timer(
$interval,
\max(0, ($watcher->expiration - $now) / self::MILLISEC_PER_SEC),
($watcher->type & Watcher::REPEAT) ? $interval : 0,
$this->timerCallback,
$watcher
Expand Down
13 changes: 3 additions & 10 deletions lib/Loop/EventDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ class EventDriver extends Driver
/** @var \Event[] */
private $signals = [];

/** @var bool */
private $nowUpdateNeeded = false;

/** @var int Internal timestamp for now. */
private $now;

Expand Down Expand Up @@ -235,10 +232,7 @@ public function stop()
*/
public function now(): int
{
if ($this->nowUpdateNeeded) {
$this->now = getCurrentTime() - $this->nowOffset;
$this->nowUpdateNeeded = false;
}
$this->now = getCurrentTime() - $this->nowOffset;

return $this->now;
}
Expand All @@ -258,7 +252,6 @@ public function getHandle(): \EventBase
*/
protected function dispatch(bool $blocking)
{
$this->nowUpdateNeeded = true;
$this->handle->loop($blocking ? \EventBase::LOOP_ONCE : \EventBase::LOOP_ONCE | \EventBase::LOOP_NONBLOCK);
}

Expand All @@ -269,7 +262,7 @@ protected function dispatch(bool $blocking)
*/
protected function activate(array $watchers)
{
$now = getCurrentTime() - $this->nowOffset;
$now = $this->now();

foreach ($watchers as $watcher) {
if (!isset($this->events[$id = $watcher->id])) {
Expand Down Expand Up @@ -335,7 +328,7 @@ protected function activate(array $watchers)
case Watcher::REPEAT:
\assert(\is_int($watcher->value));

$interval = $watcher->value - ($now - $this->now());
$interval = \max(0, $watcher->expiration - $now);
$this->events[$id]->add($interval > 0 ? $interval / self::MILLISEC_PER_SEC : 0);
break;

Expand Down
8 changes: 5 additions & 3 deletions lib/Loop/Internal/TimerQueue.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,17 @@ final class TimerQueue
* Inserts the watcher into the queue. Time complexity: O(log(n)).
*
* @param Watcher $watcher
* @param int $expiration
*
* @psalm-param Watcher<int> $watcher
*
* @return void
*/
public function insert(Watcher $watcher, int $expiration)
public function insert(Watcher $watcher)
{
$entry = new TimerQueueEntry($watcher, $expiration);
\assert($watcher->expiration !== null);
\assert(!isset($this->pointers[$watcher->id]));

$entry = new TimerQueueEntry($watcher, $watcher->expiration);

$node = \count($this->data);
$this->data[$node] = $entry;
Expand Down
14 changes: 2 additions & 12 deletions lib/Loop/NativeDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ class NativeDriver extends Driver
/** @var Watcher[][] */
private $signalWatchers = [];

/** @var bool */
private $nowUpdateNeeded = false;

/** @var int Internal timestamp for now. */
private $now;

Expand Down Expand Up @@ -71,10 +68,7 @@ public function onSignal(int $signo, callable $callback, $data = null): string
*/
public function now(): int
{
if ($this->nowUpdateNeeded) {
$this->now = getCurrentTime() - $this->nowOffset;
$this->nowUpdateNeeded = false;
}
$this->now = getCurrentTime() - $this->nowOffset;

return $this->now;
}
Expand All @@ -96,8 +90,6 @@ public function getHandle()
*/
protected function dispatch(bool $blocking)
{
$this->nowUpdateNeeded = true;

$this->selectStreams(
$this->readStreams,
$this->writeStreams,
Expand Down Expand Up @@ -292,9 +284,7 @@ protected function activate(array $watchers)
case Watcher::DELAY:
case Watcher::REPEAT:
\assert(\is_int($watcher->value));

$expiration = $this->now() + $watcher->value;
$this->timerQueue->insert($watcher, $expiration);
$this->timerQueue->insert($watcher);
break;

case Watcher::SIGNAL:
Expand Down
6 changes: 5 additions & 1 deletion lib/Loop/UvDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ public static function isSupported(): bool
*/
public function now(): int
{
\uv_update_time($this->handle);

/** @psalm-suppress TooManyArguments */
return \uv_now($this->handle);
}
Expand Down Expand Up @@ -220,6 +222,8 @@ protected function dispatch(bool $blocking)
*/
protected function activate(array $watchers)
{
$now = $this->now();

foreach ($watchers as $watcher) {
$id = $watcher->id;

Expand Down Expand Up @@ -264,7 +268,7 @@ protected function activate(array $watchers)

\uv_timer_start(
$event,
$watcher->value,
\max(0, $watcher->expiration - $now),
($watcher->type & Watcher::REPEAT) ? $watcher->value : 0,
$this->timerCallback
);
Expand Down
3 changes: 3 additions & 0 deletions lib/Loop/Watcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,7 @@ class Watcher
* @psalm-var TValue
*/
public $value;

/** @var int|null */
public $expiration;
}
Loading

0 comments on commit 05483cd

Please sign in to comment.