Here's something I wrote for guifa a couple of days ago. I am thinking of turning it into a simple Rakuish event loop for my projects.
Is this a fairly decent implementation, or is this just NIH for cron?
Please share your thoughts.
my %suppliers;
our %shifts is export;
my %times;
my $master = DateTime.now;
class TimeEvent {
has $.time is built;
}
my $minute-time = $master;
for <minute hour day week month year> {
%suppliers{$_} = Supplier::Preserving.new;
%shifts{$_} = -> { %suppliers{$_}.Supply };
%times{$_} = $master;
start loop {
await Promise.at(
Instant.from-posix: (
%times{$_} = %times{$_}.later( |("{ $_ }" => 1) ).truncated-to($_)
).posix
);
%suppliers{$_}.emit: TimeEvent.new( time => %times{$_} );
}
}
react {
whenever %shifts<minute>() -> $e {
CATCH { default { .message.say } }
say "Minute shifted for event { $e.gist }";
}
}
Let me clear this out: my primary point is to prevent extra consumption of threads. Yet, it is not even possible to get rid of at least one thread without enforcing user code to run within some kind of event loop, and let's not be that extreme! :)
Speaking of possible single-threaded implementations I have the following options in mind for the moment:
await Promise.any(@promises-for-each-interval)
– this one I just've came up with, but it would be rather cumbersome to implement.Supply.internval
for each option. Probably too much considering that most usages would stick to 1-2 options.Supply.interval
and events produced based on seconds passed since some reference point.loop
withsleep 1
and then the same as above.Not sure which approach would be the best for the task, but tend to see the last one as the most simplistic and easy to comprehend.