This makes it possible to handle events that happen at irregular
intervals: the event is created as non-repeating and the event handler
computes when the next event should happen and adds it.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/lib/WineTestBot/Engine/Events.pm | 70 ++++++++++++++----------
1 file changed, 40 insertions(+), 30 deletions(-)
diff --git a/testbot/lib/WineTestBot/Engine/Events.pm b/testbot/lib/WineTestBot/Engine/Events.pm
index 677debfbf..f1ab39ac9 100644
--- a/testbot/lib/WineTestBot/Engine/Events.pm
+++ b/testbot/lib/WineTestBot/Engine/Events.pm
@@ -37,10 +37,11 @@ sub AddEvent($$$$)
{
my ($Name, $Timeout, $Repeat, $HandlerFunc) = @_;
- $Events{$Name} = {Expires => time() + $Timeout,
- Timeout => $Timeout,
- Repeat => $Repeat,
- HandlerFunc => $HandlerFunc};
+ $Events{$Name} = { Name => $Name,
+ Expires => time() + $Timeout,
+ Timeout => $Timeout,
+ Repeat => $Repeat,
+ HandlerFunc => $HandlerFunc };
}
sub DeleteEvent($)
@@ -54,42 +55,51 @@ sub EventScheduled($)
{
my ($Name) = @_;
- return defined($Events{$Name});
+ return exists $Events{$Name};
}
sub RunEvents()
{
my $Now = time();
- my $Next = undef;
- foreach my $Name (keys %Events)
+ # Run expired events in their expiration order.
+ # Note that callbacks may add / remove events.
+ my @SortedEvents = sort { $a->{Expires} <=> $b->{Expires} } values %Events;
+ foreach my $Event (@SortedEvents)
{
- my $Event = $Events{$Name};
- if (defined($Event))
+ if (!exists $Events{$Event->{Name}})
+ {
+ # This event got removed by a callback
+ next;
+ }
+
+ if ($Event->{Expires} > $Now)
+ {
+ # Since the events are sorted by expiration order,
+ # there is no other event to run.
+ last;
+ }
+
+ if ($Event->{Repeat})
{
- if ($Event->{Expires} <= $Now)
- {
- if ($Event->{Repeat})
- {
- $Event->{Expires} += $Event->{Timeout};
- if (! defined($Next) || $Event->{Expires} - $Now < $Next)
- {
- $Next = $Event->{Expires} - $Now;
- }
- }
- else
- {
- delete $Events{$Name};
- }
- &{$Event->{HandlerFunc}}();
- }
- elsif (! defined($Next) || $Event->{Expires} - $Now < $Next)
- {
- $Next = $Event->{Expires} - $Now;
- }
+ $Event->{Expires} += $Event->{Timeout};
}
+ else
+ {
+ delete $Events{$Event->{Name}};
+ }
+ &{$Event->{HandlerFunc}}();
}
- return $Next;
+ # Determine when the next event is due
+ my $Next = undef;
+ foreach my $Event (values %Events)
+ {
+ if (!defined $Next or $Event->{Expires} - $Now < $Next)
+ {
+ $Next = $Event->{Expires} - $Now;
+ }
+ }
+ return $Next <= 0 ? 1 : $Next;
}
1;
--
2.17.0