SPVM-Go
view release on metacpan or search on metacpan
lib/SPVM/Go/Schedule/Task.spvm view on Meta::CPAN
# Copyright (c) 2023 Yuki Kimoto
# MIT License
class Go::Schedule::Task {
allow Go::Schedule;
use Sys::Time;
use Sys::Time::Timespec;
use Sys::Poll::PollfdArray;
use Sys::Poll::Constant as POLL;
use Sys::Poll;
has schedule : Go::Schedule;
private static method new : Go::Schedule::Task () {
my $self = new Go::Schedule::Task;
return $self;
}
private method : void () {
my $schedule = $self->{schedule};
my $poll = $schedule->{poll};
my $loop_count = 0;
while (1) {
my $coroutines = $schedule->{coroutines};
if ($coroutines->length == 0) {
last;
}
my $check_io = $loop_count % 60 == 0;
if ($check_io) {
$poll->check;
}
else {
my $coroutine = (Go::Coroutine)undef;
if ($coroutines->length > 0) {
$coroutine = (Go::Coroutine)$coroutines->get(0);
}
if ($coroutine->{finished}) {
$coroutines->shift;
$schedule->{current_coroutine} = undef;
if (Go->ENV_DEBUG) {
Fn->say_stderr(Fn->sprintf("[Go Debug]End goroutine (Callback:%p, QueueNum:%d.)", [(object)$coroutine->{task}, $coroutines->length]));
}
}
elsif ($coroutine->{disable}) {
$coroutines->push($coroutines->shift);
if (Go->ENV_DEBUG) {
Fn->say_stderr(Fn->sprintf("[Go Debug]Rotate IO goroutine (Callback:%p, QueueNum:%d.)", [(object)$coroutine->{task}, $coroutines->length]));
}
}
else {
my $is_over_deadline = 0;
my $deadline_base_timer = $coroutine->{deadline_base_timer};
my $after = $coroutine->{after};
if ($deadline_base_timer) {
$is_over_deadline = Go::Schedule->is_over_deadline($deadline_base_timer, $after);
if ($is_over_deadline) {
$coroutine->{deadline_base_timer} = undef;
}
else {
$coroutines->push($coroutines->shift);
if (Go->ENV_DEBUG) {
Fn->say_stderr(Fn->sprintf("[Go Debug]Rotate timer goroutine (Callback:%p, QueueNum:%d)", [(object)$coroutine->{task}, $coroutines->length]));
}
}
}
else {
$is_over_deadline = 1;
}
my $fd = $coroutine->{fd};
if ($fd >= 0) {
$coroutine->{disable} = 1;
my $coroutine_address = Fn->to_address($coroutine);
$schedule->{poll}->{coroutines_h}->set($coroutine_address, $coroutine);
$coroutines->push($coroutines->shift);
if (Go->ENV_DEBUG) {
Fn->say_stderr(Fn->sprintf("[Go Debug]Rotate IO goroutine first time (Callback:%p, QueueNum:%d.)", [(object)$coroutine->{task}, $coroutines->length]));
}
}
else {
if ($is_over_deadline) {
my $schedule_task_coroutine = $schedule->{schedule_task_coroutine};
$coroutines->push($coroutines->shift);
$coroutine->{return_back} = $schedule_task_coroutine;
$schedule->{current_coroutine} = $coroutine;
Go::Coroutine->transfer($schedule_task_coroutine, $coroutine);
if (Go->ENV_DEBUG) {
Fn->say_stderr(Fn->sprintf("[Go Debug]Start or resume goroutine (Callback:%p, QueueNum:%d.)", [(object)$coroutine->{task}, $coroutines->length]));
}
}
}
}
}
$loop_count++;
}
}
}
( run in 1.654 second using v1.01-cache-2.11-cpan-39bf76dae61 )