3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-11-29 23:39:24 +01:00

Timer: intelligently wait for next tick; eventqueue command can now filter

This commit is contained in:
Pragmatic Software 2020-03-06 20:23:17 -08:00
parent bc79f3a69d
commit 5624d2d166

View File

@ -25,12 +25,12 @@ use feature 'unicode_strings';
use Time::Duration qw/concise duration/; use Time::Duration qw/concise duration/;
our $seconds ||= 0; our $seconds ||= 0;
our $waitfor ||= 1;
our @timer_funcs; our @timer_funcs;
# alarm signal handler (poor-man's timer) # alarm signal handler (poor-man's timer)
$SIG{ALRM} = sub { $SIG{ALRM} = sub {
$seconds += 1; $seconds += $waitfor;
alarm 1;
foreach my $func (@timer_funcs) { &$func; } foreach my $func (@timer_funcs) { &$func; }
}; };
@ -53,18 +53,33 @@ sub event_queue_cmd {
return "No events queued." if not @{$self->{event_queue}}; return "No events queued." if not @{$self->{event_queue}};
my $text = "Queued events:\n"; my $result = eval {
my $text = "Queued events:\n";
my $i = 0; my $i = 0;
foreach my $event (@{$self->{event_queue}}) { foreach my $event (@{$self->{event_queue}}) {
my $duration = concise duration $event->{timeout} - $seconds; $i++;
$text .= " $i) in $duration: $event->{id}";
$text .= ' [R]' if $event->{repeating}; if ($arguments) {
$text .= ";\n"; next unless $event->{id} =~ /$arguments/;
$i++; }
my $duration = concise duration $event->{timeout} - $seconds;
$text .= " $i) in $duration: $event->{id}";
$text .= ' [R]' if $event->{repeating};
$text .= ";\n";
}
return $text;
};
if ($@) {
my $error = $@;
$error =~ s/ at PBot.*//;
return "Bad regex: $error";
} }
return $text; return $result;
} }
sub start { sub start {
@ -104,6 +119,9 @@ sub find_enqueue_position {
} elsif ($value > $self->{event_queue}->[$mid]->{timeout}) { } elsif ($value > $self->{event_queue}->[$mid]->{timeout}) {
$lo = $mid + 1; $lo = $mid + 1;
} else { } else {
while ($mid < @{$self->{event_queue}} and $self->{event_queue}->[$mid]->{timeout} == $value) {
$mid++;
}
return $mid; return $mid;
} }
} }
@ -128,6 +146,10 @@ sub enqueue_event {
my $i = $self->find_enqueue_position($event->{timeout}); my $i = $self->find_enqueue_position($event->{timeout});
splice @{$self->{event_queue}}, $i, 0, $event; splice @{$self->{event_queue}}, $i, 0, $event;
if ($interval < $waitfor) {
$self->waitfor($interval);
}
my $debug = $self->{pbot}->{registry}->get_value('timer', 'debug') // 0; my $debug = $self->{pbot}->{registry}->get_value('timer', 'debug') // 0;
if ($debug > 1) { if ($debug > 1) {
$self->{pbot}->{logger}->log("Enqueued new timer event $id at position $i: timeout=$event->{timeout} interval=$interval repeating=$repeating\n"); $self->{pbot}->{logger}->log("Enqueued new timer event $id at position $i: timeout=$event->{timeout} interval=$interval repeating=$repeating\n");
@ -160,6 +182,17 @@ sub unregister {
$self->dequeue_event($id); $self->dequeue_event($id);
} }
sub update_repeating {
my ($self, $id, $repeating) = @_;
for (my $i = 0; $i < @{$self->{event_queue}}; $i++) {
if ($self->{event_queue}->[$i]->{id} eq $id) {
$self->{event_queue}->[$i]->{repeating} = $repeating;
last;
}
}
}
sub update_interval { sub update_interval {
my ($self, $id, $interval, $dont_enqueue) = @_; my ($self, $id, $interval, $dont_enqueue) = @_;
@ -176,6 +209,13 @@ sub update_interval {
} }
} }
sub waitfor {
my ($self, $duration) = @_;
$duration = 1 if $duration < 1;
alarm $duration;
$waitfor = $duration;
}
sub on_tick_handler { sub on_tick_handler {
my ($self) = @_; my ($self) = @_;
return if not $self->{enabled}; return if not $self->{enabled};
@ -183,23 +223,28 @@ sub on_tick_handler {
my $debug = $self->{pbot}->{registry}->get_value('timer', 'debug') // 0; my $debug = $self->{pbot}->{registry}->get_value('timer', 'debug') // 0;
$self->{pbot}->{logger}->log("$self->{name} tick $seconds\n") if $debug; $self->{pbot}->{logger}->log("$self->{name} tick $seconds\n") if $debug;
my $next_tick = 1;
if (@{$self->{event_queue}}) { if (@{$self->{event_queue}}) {
my @enqueue = (); my @enqueue = ();
for (my $i = 0; $i < @{$self->{event_queue}}; $i++) { for (my $i = 0; $i < @{$self->{event_queue}}; $i++) {
if ($seconds >= $self->{event_queue}->[$i]->{timeout}) { if ($seconds >= $self->{event_queue}->[$i]->{timeout}) {
my $event = $self->{event_queue}->[$i]; my $event = $self->{event_queue}->[$i];
$self->{pbot}->{logger}->log("Processing timer event $i: $event->{id}\n") if $debug > 1; $self->{pbot}->{logger}->log("Processing timer event $i: $event->{id}\n") if $debug > 1;
$event->{subref}->($self); $event->{subref}->($event);
splice @{$self->{event_queue}}, $i--, 1; splice @{$self->{event_queue}}, $i--, 1;
push @enqueue, $event if $event->{repeating}; push @enqueue, $event if $event->{repeating};
} else { } else {
if ($debug > 2) { if ($debug > 2) {
$self->{pbot}->{logger}->log("Event not ready yet: $self->{event_queue}->[$i]->{id} (timeout=$self->{event_queue}->[$i]->{timeout})\n"); $self->{pbot}->{logger}->log("Event not ready yet: $self->{event_queue}->[$i]->{id} (timeout=$self->{event_queue}->[$i]->{timeout})\n");
} }
$next_tick = $self->{event_queue}->[$i]->{timeout} - $seconds;
last; last;
} }
} }
$self->waitfor($next_tick);
foreach my $event (@enqueue) { foreach my $event (@enqueue) {
$self->enqueue_event($event->{subref}, $event->{interval}, $event->{id}, 1); $self->enqueue_event($event->{subref}, $event->{interval}, $event->{id}, 1);
} }
@ -209,6 +254,8 @@ sub on_tick_handler {
$self->{last} = $seconds; $self->{last} = $seconds;
$self->on_tick; $self->on_tick;
} }
$self->waitfor($self->{timeout} - $seconds - $self->{last});
} }
} }