34 private bool $enabled =
true;
45 protected int $currentTick = 0;
47 public function __construct(
48 private ?
string $owner =
null
55 return $this->addTask($task, -1, -1);
58 public function scheduleDelayedTask(Task $task,
int $delay) : TaskHandler{
59 return $this->addTask($task, $delay, -1);
62 public function scheduleRepeatingTask(Task $task,
int $period) : TaskHandler{
63 return $this->addTask($task, -1, $period);
66 public function scheduleDelayedRepeatingTask(Task $task,
int $delay,
int $period) : TaskHandler{
67 return $this->addTask($task, $delay, $period);
70 public function cancelAllTasks() : void{
71 foreach($this->tasks as $id => $task){
74 $this->tasks->clear();
75 while(!$this->queue->isEmpty()){
76 $this->queue->extract();
80 public function isQueued(TaskHandler $task) : bool{
81 return $this->tasks->contains($task);
84 private function addTask(Task $task,
int $delay,
int $period) : TaskHandler{
86 throw new \LogicException(
"Tried to schedule task to disabled scheduler");
99 return $this->handle(
new TaskHandler($task, $delay, $period, $this->owner));
102 private function handle(TaskHandler $handler) : TaskHandler{
103 if($handler->isDelayed()){
104 $nextRun = $this->currentTick + $handler->getDelay();
106 $nextRun = $this->currentTick;
109 $handler->setNextRun($nextRun);
110 $this->tasks->add($handler);
111 $this->queue->insert($handler, $nextRun);
116 public function shutdown() : void{
117 $this->enabled = false;
118 $this->cancelAllTasks();
121 public function setEnabled(
bool $enabled) : void{
122 $this->enabled = $enabled;
125 public function mainThreadHeartbeat(
int $currentTick) : void{
127 throw new \LogicException(
"Cannot run heartbeat on a disabled scheduler");
129 $this->currentTick = $currentTick;
130 while($this->isReady($this->currentTick)){
132 $task = $this->queue->extract();
133 if($task->isCancelled()){
134 $this->tasks->remove($task);
138 if(!$task->isCancelled() && $task->isRepeating()){
139 $task->setNextRun($this->currentTick + $task->getPeriod());
140 $this->queue->insert($task, $this->currentTick + $task->getPeriod());
143 $this->tasks->remove($task);
148 private function isReady(
int $currentTick) : bool{
149 return !$this->queue->isEmpty() && $this->queue->current()->getNextRun() <= $currentTick;