Reputation: 12200
I'm using EV module to create a timed events that will run indefinitely in a defined time interval, here is my code with defined intervals.
#!/usr/bin/perl
use strict;
use warnings qw/ all FATAL /;
use feature 'say';
use EV;
use Time::Piece 'localtime';
my $one_sec = EV::timer 1,1, sub {
say "(1s) Periodic event at ", localtime(EV::now)->hms;
};
my $five_sec = EV::timer 5, 5, sub {
say "(5s) Periodic event at ", localtime(EV::now)->hms;
};
EV::run;
I'm trying to define these functions dynamically from hash reference, by looping through it to create these functions.
my $hash = {
'one_sec' => '1',
'five_sec' => '5',
};
I have used foreach to loop through the hash.
foreach my $key ( keys %$hash )
{
my $key = EV::timer $hash->{$key},$hash->{$key}, sub {
say "($hash->{$key}) Periodic event at ", localtime(EV::now)->hms;
};
EV::run;
}
It works, but only for the first iteration, I'm not sure why is that?
Your thoughts are highly appreciated.
Upvotes: 1
Views: 289
Reputation: 54373
The following code is not tested.
There are two things wrong with your code:
First, you are starting the event loop in the body of your foreach
loop, which will make it run within the first iteration of the foreach
. It will then get stuck there, and only one of the timers will be created. To fix that, the EV::run
needs to be moved to outside of the foreach
.
However, it will then not do anything at all. That's because the event-loop has nothing to do. That is because you are defining your EV::timer
objects lexically within the body of the foreach
. Once one iteration is done, that variable ($key
) will go out of scope, destroying the timer object. When it's done creating both, it will just run an empty event-loop. In addition to that, you redefined $key
, which was already the "one_sec"
or "five_sec"
string that comes out of the hash.
Instead, you need to put the event objects somewhere that's outside of the loop, too (because each block creates a lexical scope in Perl when you use my
, which is a feature).
You should also use more speaking variable names so you don't get confused.
#!/usr/bin/perl
use strict;
use warnings qw/ all FATAL /;
use feature 'say';
use EV;
use Time::Piece 'localtime';
my $config = { # was $hash
'one_sec' => '1',
'five_sec' => '5',
}
my $timers;
foreach my $key ( keys %$config ) {
$timers->{$key} = EV::timer $config->{$key},$config->{$key}, sub {
say "($config->{$key}) Periodic event at ", localtime(EV::now)->hms;
};
}
EV::run;
Upvotes: 2