Hello,
I was talking with another programmer about Event, and we came to a
point where he asked me if repeat(0)/repeat(1) is synonym to
stop()/start(). This seems to be underdocumented, so I wrote this hack
to check it:
- snip --
use strict;
use Event;
my $w=Event->io(fd=>\*STDIN, repeat=>0, cb=>\&callback);
Event->timer(interval=>5, cb=>sub {$w->repeat(0); warn "INACTIVE\n";
state($w);});
Event->timer(interval=>3.721, cb=>sub {$w->repeat(1); warn "ACTIVE!!\n";
state($w);});
Event::loop;
sub callback
{my $h=$_[0]->w->fd; my $in=<$h>; print "You entered: $in";
state($_[0]->w);}
sub state
{
# get operation
my ($w)=@_;
# report state
warn "active=>", $w->is_active, ", suspended=>", $w->is_suspended, ",
cancelled=>", $w->is_cancelled, ".\n";
}
- snip --
This script implements a one shot watcher which is activated and
deactivated by several timers via repeat(). Some thoughts:
Until this question, I expected that a one shot watcher automatically
becomes INACTIVE after callback invokation. But if you run the script,
you can see that the repeat() method surprisingly does not influence the
activity flag EVEN AFTER CALLBACK INVOKATION. So we have an active
watcher behaving like an inactive one after callback invokation. If you
observe such a watcher by ProcessTop, it is reported as "zombie", but as
the programmer proposed, different to usual zombies it can be reanimated
by a call of repeat(1).
So, to sum it up, thanks to this proposal I discovered this unexpected
usage of the repeat() method. My question is if it is necessary to
implement it that hidden way - there seems to exist an additional
internal flag. Wouldn't it make the interface clearer if repeat(0) would
enforce a watcher to become simply INACTIVE after callback invokation?
This would allow to reuse the watcher later on by simply calling again()
- for just another one shot activity (the repeat attribute would remain
unchanged). repeat(1), on the other hand, should just set the attribute
in my opinion, as well as other attribute methods do. It should not
reactivate the watcher.
My aim with all this is an easy to use, clear interface - if possible,
all attribute methods should behave the same way. And if possible, the
state methods is_active() etc. should reflect the real behaviour. This
means if a user finds out a watcher is ACTIVE because this is reported
by is_active(), the watcher should BEHAVE actively - detecting events
and queuing them. By now, is_active() says something like: "I'm active,
except if my repeat attribute is 0 and the callback was already invoked,
so please check this as well."
Just another point. The script above runs well on Solaris, but on Linux
it behaves differently. If you enter something in STDIN on Linux while
the script reports to be "INACTIVE", the screen is filled by a message
that an event arrived for an "!ACTIVE" watcher. This message is
displayed again and again, and it seems the loop is out of control then,
no callback is invoked after this.
Jochen