123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- <?php
- declare(strict_types=1);
- /**
- * This file is part of Hyperf.
- *
- * @link https://www.hyperf.io
- * @document https://hyperf.wiki
- * @contact group@hyperf.io
- * @license https://github.com/hyperf/hyperf/blob/master/LICENSE
- */
- namespace Hyperf\Coordinator;
- use Psr\Log\LoggerInterface;
- use Throwable;
- use function Hyperf\Coroutine\go;
- class Timer
- {
- public const STOP = 'stop';
- private array $closures = [];
- private int $id = 0;
- private static int $count = 0;
- private static int $round = 0;
- public function __construct(private ?LoggerInterface $logger = null)
- {
- }
- public function after(float $timeout, callable $closure, string $identifier = Constants::WORKER_EXIT): int
- {
- $id = ++$this->id;
- $this->closures[$id] = true;
- go(function () use ($timeout, $closure, $identifier, $id) {
- try {
- ++Timer::$count;
- $isClosing = match (true) {
- $timeout > 0 => CoordinatorManager::until($identifier)->yield($timeout), // Run after $timeout seconds.
- $timeout == 0 => CoordinatorManager::until($identifier)->isClosing(), // Run immediately.
- default => CoordinatorManager::until($identifier)->yield(), // Run until $identifier resume.
- };
- if (isset($this->closures[$id])) {
- $closure($isClosing);
- }
- } finally {
- unset($this->closures[$id]);
- --Timer::$count;
- }
- });
- return $id;
- }
- public function tick(float $timeout, callable $closure, string $identifier = Constants::WORKER_EXIT): int
- {
- $id = ++$this->id;
- $this->closures[$id] = true;
- go(function () use ($timeout, $closure, $identifier, $id) {
- try {
- $round = 0;
- ++Timer::$count;
- while (true) {
- $isClosing = CoordinatorManager::until($identifier)->yield(max($timeout, 0.000001));
- if (! isset($this->closures[$id])) {
- break;
- }
- $result = null;
- try {
- $result = $closure($isClosing);
- } catch (Throwable $exception) {
- $this->logger?->error((string) $exception);
- }
- if ($result === self::STOP || $isClosing) {
- break;
- }
- ++$round;
- ++Timer::$round;
- }
- } finally {
- unset($this->closures[$id]);
- Timer::$round -= $round;
- --Timer::$count;
- }
- });
- return $id;
- }
- public function until(callable $closure, string $identifier = Constants::WORKER_EXIT): int
- {
- return $this->after(-1, $closure, $identifier);
- }
- public function clear(int $id): void
- {
- unset($this->closures[$id]);
- }
- public function clearAll(): void
- {
- $this->closures = [];
- }
- public static function stats(): array
- {
- return [
- 'num' => Timer::$count,
- 'round' => Timer::$round,
- ];
- }
- }
|