While trying to understand AnyEvent, I create two timers which print to screen each time they're fired. Initially neither worked. But following Joshua Barratt's timer example, I found that if I didn't undef
the timer's watcher variable then the timer's callback didn't fire at all. Why is that the case? I suspect it has something to do with how scope works in perl and/or AnyEvent.
Here is my example program:
#!/usr/bin/perl
use AE;
my $cv = AE::cv;
sub func1 {
my $spoke = 0;
my $t1; $t1 = AE::timer 0, 1,
sub {
print "Timer 1 Fired\n";
if($spoke++ > 5) {
print "Timer 1 Done\n";
undef $t1;
}
};
print "Timer 1 started\n";
}
sub func2 {
my $spoke = 0;
my $t2; $t2 = AE::timer 0, 1,
sub {
print "Timer 2 Fired\n";
if($spoke++ > 5) {
print "Timer 2 Done\n";
#undef $t2;
}
};
print "Timer 2 started\n";
}
func1();
func2();
$cv->recv;
As is, my code returns:
Timer 1 started
Timer 2 started
Timer 1 Fired
Timer 1 Fired
Timer 1 Fired
Timer 1 Fired
Timer 1 Fired
Timer 1 Fired
Timer 1 Fired
Timer 1 Done
If I uncomment the undef $t2;
line, Timer 2's callback is fired and I get this:
Timer 1 started
Timer 2 started
Timer 1 Fired
Timer 2 Fired
Timer 2 Fired
Timer 1 Fired
Timer 1 Fired
Timer 2 Fired
Timer 2 Fired
Timer 1 Fired
Timer 1 Fired
Timer 2 Fired
Timer 2 Fired
Timer 1 Fired
Timer 1 Fired
Timer 1 Done
Timer 2 Fired
Timer 2 Done
You must keep the guard object (the value of $t1
) alive. If all references to it are gone, it will get destroyed, and that cancels the event.
Referencing $t1
in the closure causes the closure to capture it, keeping it alive past it's normal death at then end of func
.
If you want to capture a variable you don't otherwise need, you can use
$t2 if 0; # Keep timer alive until process exit.
Here's a simple example of a closure:
sub make_closure {
my ($x) = @_;
return sub {
print("$x\n");
};
}
my $f1 = make_closure("Hello, World!");
my $f2 = make_closure("Allo, Jeune Renard!");
$f1->();
$f2->();
Notice how the closure (the anon sub) captures the $x
that existed at the time?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With