diff --git a/kiri-actor/Actor.php b/kiri-actor/Actor.php index dd687651..3b6b8463 100644 --- a/kiri-actor/Actor.php +++ b/kiri-actor/Actor.php @@ -22,6 +22,12 @@ abstract class Actor implements ActorInterface, JsonSerializable private bool $isShutdown = false; + /** + * @var int + */ + private int $messageId = -1; + + /** * @var int */ @@ -40,6 +46,12 @@ abstract class Actor implements ActorInterface, JsonSerializable private float $startTime = 0; + /** + * @var int + */ + private int $refreshInterval = 0; + + /** * @return ActorState */ @@ -77,7 +89,6 @@ abstract class Actor implements ActorInterface, JsonSerializable } - /** * @return void */ @@ -87,6 +98,15 @@ abstract class Actor implements ActorInterface, JsonSerializable } + /** + * @return bool + */ + public function isShutdown(): bool + { + return $this->isShutdown; + } + + /** * @param $id * @return static @@ -136,10 +156,20 @@ abstract class Actor implements ActorInterface, JsonSerializable public function shutdown(): void { $this->isShutdown = true; + Coroutine::cancel($this->coroutineId); + if ($this->messageId > -1) { + Coroutine::cancel($this->messageId); + } $this->channel->close(); } + /** + * @return void + */ + abstract public function onUpdate(): void; + + /** * @return void */ @@ -147,21 +177,44 @@ abstract class Actor implements ActorInterface, JsonSerializable { $this->setState(ActorState::BUSY); $this->init(); - $this->loop(); + $this->messageId = Coroutine::create(fn() => $this->loop()); + $this->interval(); $this->setState(ActorState::IDLE); } /** - * @return mixed + * @return void */ - private function loop(): mixed + private function interval(): void { + if ($this->isShutdown()) { + return; + } + $this->onUpdate(); + + Coroutine::sleep($this->refreshInterval / 1000); + + $this->interval(); + } + + + /** + * @return bool + */ + private function loop(): bool + { + if ($this->messageId == -1) { + $this->messageId = Coroutine::getCid(); + } if ($this->channel->errCode == SWOOLE_CHANNEL_CLOSED) { $this->channel = new Channel(99); } $message = $this->channel->pop(); $this->process($message); + if ($this->isShutdown()) { + return true; + } return $this->loop(); }