NAME
Event - Event loop processing
SYNOPSIS
use Event qw(loop unloop);
# initialize application
Event->type(attribute => value, ...);
my $ret = loop();
# and some callback will call
unloop('ok');
DESCRIPTION
The Event module provide a central facility to watch for various types of events and invoke a callback when these events occur. The central idea is to delay the handling of events in order that they can be dispatched by priority and also when it is known to be safe for callbacks to execute.
API
Events (the occurance of such) are noticed and queued by event watchers. The creation and configuration of event watchers is the primary topic of the rest of this document.
The following functions control and interrogate the event loop as a whole:
- $result = loop([$timeout])
-
Will enter a loop that calls one_event() until unloop() is called. The argument passed to unloop() is the return value of loop(). Loops can be nested.
- unloop($result)
-
Make the inner-most loop() return with $result.
- unloop_all()
-
Cause all pending loop()s to return immediately. This is not implemented with
die
. It is implemented to work as ifunloop(undef)
was called for all pending loops. - sweep([$max_prio])
-
Queue all pending events and process the ones with priority higher than $max_prio. The default is to process all events except idle events. (Idle events are ignored by sweep.)
- one_event([$timeout])
-
If any events are outstanding then invoke the corresponding callback of the highest priority event. If there are no events available, block until forever or until $timeout. Use of this API is not recommended because it doesn't trap exceptions and is not very efficient.
- all_watchers()
-
Returns a list of all watchers (including stopped events).
- all_running()
-
Returns a list of all watchers with active callbacks. Watchers are returned in order of most recent to least recent.
- all_idle()
-
Return all watchers on the idle queue.
Event Watcher Constructors
All watchers are constructed in one of the following ways:
$w = Event->type( [e_attr1 => $value,]... );
or
use Event::type;
$w = Event::type( [e_attr1 => $value,]...);
Where type is substituted with the kind of watcher. Built-in types include idle, inactivity, io, signal, timer, and var.
The new watcher object either has reasonable defaults or can be customized by passing attributes to the constructor. When created, watcher objects are "started" and already waiting for events (see $event->start
below).
Shared Watcher Attributes
Watchers are configured with attributes (also called properties). This is a fancy way of saying that a watcher object works like hash reference. For example:
$watcher->{e_cb} = \&some_code; #callback
print "$watcher->{e_hits} events happened; Wow!\n";
The Event modules reserves all keys beginning with 'e_'. You are free to use other keys for any purpose.
The following attributes are supported by all types of watchers. Most watchers also offer additional attributes to customize their particular specialty.
- e_id => $int
-
An integer that uniquely identifies a watcher. This attribute is read-only. You should use this to test for equality (until the equality test for tied objects is fixed).
- e_cb => \&code
- e_cb => [$class_or_object, $method]
-
The function or method to call when an event happens. The callback is invoked with the
$event
as its only argument. An$event
works like a watcher except that it has a few extra hash keys which are event specific.Perhaps you are wondering what happens if something goes wrong and an untrapped
die
occurs within your callback?$Event::DIED
is just for this purpose. See the full description ofDIED
below. - e_clump => $bool
-
If an event occurs many times before any events can be processed then a watcher must record this somehow. Currently there are two choice. If clump is false then a new event will be generated for each occurance of an event. On the other hand, if clump is true then each event occurance will increment
e_hits
. Clumping is slightly more efficient than not clumping. - e_hits => $int
-
A watcher increments
e_hits
every time it registers an event. This is usually only relevant ife_clump
is enabled. This attribute is read-only. - e_prio => $int
-
Priority is used to order events queued for processing. Meaningful priorities range from -1 to 6 inclusive. Lower numbers mean higher priority (-1 is the highest priority and 6 is the lowest). When multiple events happen, the events with the highest priority are serviced firstly.
A negative priority indicates that the callback should be invoked immediately upon event occurance. Use this with caution. While it may seem advantageous to use negative priorities it defeats the purpose of even having an event queue in the first place.
Also of note: you cannot set the priority with event constructors. Instead use
e_nice
to specify an offset from the default priority. (Each event type has a default priority.) - e_desc => $string
-
Some identifying name. If not passed explicitly to the constructor, it will be initialized with some string that attempts to identify the location in the source code where the watcher was constructed.
- e_flags => $bits
-
The
e_flag
attribute encodes some information about the state of an event. [XXX Fill in exact bits] - e_repeat => $bool
-
The repeat flag controls whether callback should be one-shot or if the watcher should continue waiting for new events of this kind occur. The default depends on the type of watcher. io, signal, and var default to true.
- e_debug => $bool
-
Debugging can be activated globally or per watcher. When debugging is enabled for a particular watcher, $Event::DebugLevel is treated as two levels higher. Levels of 1, 2, 3, or 4 give progressively more diagnostics on STDERR.
- e_reentrant => $bool
-
By default, callbacks are allowed to invoke
sweep
orloop
which in turn may invoke the same callback again recursively. This can be useful, but can also be confusing. Disable this feature per watcher by setting reentrant to false. This will cause the watcher to be suspended during recursive calls tosweep
orloop
.
Shared Watcher Methods
The following methods can be invoked on an event:
- $watcher->start
-
Activate the watcher. Many constructors will automatically invoke $watcher->start.
- $watcher->again
-
Same as the
start
method except in the case of watchers with special repeat behavior. For example, repeating timers recalcuate their alarm time using thee_interval
parameter. - $watcher->stop
-
Don't look for events any more. Note that a stopped watcher can be reactivated by calling the
start
oragain
methods. - $watcher->cancel
-
Stop and unconditionally destroy
$watcher
. If an attempt to made to use$watcher
after callingcancel
then an exception will be thrown. - $watcher->suspend
-
A suspended watcher will stop queuing events until it is resumed.
- $watcher->resume
-
Revives a watcher that has been suspended.
- $watcher->now
-
Make the watcher callback trigger now. The callback may or may not run immediately depending upon the watcher's priority.
Watcher Types
- idle
-
The callback is invoked only if no other event is pending.
- var
-
Extra attribute: e_var => \$var, e_poll => 'rw'
Triggered when the value of
$var
is read or modified. - timer
-
Extra attributes: e_at => $time, e_interval => $sec, e_hard => $bool
The
$time
and$sec
are in seconds. Fractional seconds may be used if Time::HiRes is available.If
e_interval
set then the watcher will automatically reshedule repeatedly. Be aware that due to lags in the event loop thee_interval
timeout may already be in the past. If thee_hard
flag is set, the event will be queued for execution relative to the last time the callback was invoke. However, ife_hard
is false the new timeout will be calculated relative to the current time (this is the default).The constructor also accepts an
e_after
attribute for quick initialization. - io
-
Extra attributes: e_fd => $fd, e_poll => "rwe", e_got => "rwet", [e_timeout => $seconds]
The callback is invoked when the file descriptor,
e_fd
, has data to be read, written, or pending exceptions.e_fd
can be a glob, an IO::Handle object, or a file number (file descriptor). Thee_poll
attribute specifies which events to watch for. It consist of a string of letters representing flags. "r" indicates readable. "w" indicates writable. "e" indicates pending exceptions.When the callback is invoked,
e_got
is set to tell you which conditions ofe_poll
were triggered. Thee_got
attribute is read-only. If you think testing for letters is too slow you can also usee_got
as a bit mask. The bit constants are exportable from Event::Watcher.Note that it is your choice whether to have multiple watchers per file descriptor or a single watcher to handle all conditions.
- signal
-
Extra attribute: e_signal => $str
The callback will be invoked when the specified signal is received. The $str string should be something like 'INT' or 'QUIT'. See the documentation on
%SIG
for a list. - semaphore
-
Not implemented.
- msg
-
Not implemented.
CUSTOMIZATION
While the bulk of Event's implementation is in C (for maximum performance), a broad range of customization hooks are available.
$Event::DebugLevel
Enables progressively more debugging output. Meaningful levels range from 1 (least output) to 5 (most output). Also see e_debug.
$Event::Eval
Strictly for debugging. Do not enable this unless you know what you are doing.
$Event::DIED
When
loop
orsweep
is called, an exception context is established that lasts throughout event processing. If an exception is detected then$Event::DIED
is invoked:$Event::DIED->($watcher, $@);
The default hook uses
warn
to print the exception. After the DIED handler returns, event processing continues as if nothing happened. If you'd like to see more detailed output you can use the verbose handler (below) or write your own.$Event::DIED = \&Event::verbose_exception_handler;
Event->add_hooks(key => sub { ... }, ...);
The
add_hooks
method allows customization at key junctures in the optimized event processes core. The currently support hooks are listed below:hook purpose ------------- ---------------------------------------------- prepare returns minimum time to block (timeable) check assess state after normal return from select/poll asynccheck check for signals, etc callback invoked before each event callback
C API
Event also has a direct C API for high-performance event dispatching. See Event::MakeMaker.
WHAT ABOUT THREADS?
Event loops and threads are two different solutions to the same problem: asynchronous processing.
Event loops have been around since the beginning of computing. They are well understood and proven to be a good solution for many applications. While they make use of basic operating system services, the bulk of their implementation is usually outside the kernel. Therefore, while an event loop may appear to do many things in parallel, it does not. Actions are always executed sequentially. This implies that long running callbacks must be avoided because they halt event processing.
Event loops work well when actions are short and to the point. Long-running tasks must be broken into short steps and scheduled for execution. Some sort of a state machine is usually required. For example, consider a JPEG file download and render. When some new bytes are available they must be sorted to the right place on the screen. Quite a lot of state must be kept to keep track of how much has been rendered and how to process subsequent incoming bytes. While a web browser can easily get by without threads, a big complex web application server might be a great deal simpler to implement in a multithreaded fashion.
Threads can either substitute for an event loop or complement it. Threads are similar to processes in that the operating system manages task switching for you. However, the difference is that all threads share the same address space. This is good and bad. Much higher performance can be acheived, but since data is shared between threads extreme care must be taken when accessing or modifying global data. The operating system can switch threads at any moment or can execute multiple threads simultaineously. I hope this sounds dangerous! It is. Threads can introduce maddeningly complicated and hard to debug syncronization problems. Threads are like rocket fuel. They are essential when you really need them but most applications would be better off with a simple event loop. Even if threads are genuinely needed, consider confining them to the parts of an application where truly scalable performance is really worth the difficulty of a thread safe implementation. For example, most GUIs applications do not need threads and most scientific compute intensive problems can be isolated from event dispatching. On the other hand, high performance transaction servers generally do need a truly multithreaded implementation.
Another consideration is that threads are not quite as widely available as event loops. While a few forward-thinking operating systems have offered threads since the beginning, their addition to many popular operating systems is much more recent and some still offer no threads support. If portability is a requirement, one must check that threads support is available and also carefully test to be sure that a particular threads implementation supports the features you need. It is likely that all platforms will have a solid implementation soon, but at this point in history it is best to double check.
BUGS
bless
does not work with watchers. If you attempt to bless
a watcher into a different class, the blessing will not stick. The class will revert back to the original class. Unfortunately, this cannot really be fixed properly until perl has better support for custom data types.
The meaning of $io->{e_timeout}=0 might change. Use undef
to unset the timeout.
ALSO SEE
Time::HiRes and NetServer::ProcessTop.
SUPPORT
Please direct your insights and complaints to the perl-loop@perl.org mailing list!
AUTHORS
Joshua N. Pritikin <bitset@mindspring.com>
Initial 0.01 implementation by Graham Barr <gbarr@pobox.com>. Also, contributions from:
Gisle Aas E<lt>F<gisle@aas.no>E<gt>
E<lt>F<jan.dubois@ibm.net>E<gt> (Win32)
E<lt>F<Matija.Grabnar@arnes.si>E<gt> (File::Tail)
Nick Ing-Simmons E<lt>F<nick@ni-s.u-net.com>E<gt> (Tk)
Mark Mielke E<lt>F<Mark.Mielke.markm@nt.com>E<gt>
Sarathy E<lt>F<gsar@engin.umich.edu>E<gt>
COPYRIGHT
Copyright © 1997-1999 Joshua Nathaniel Pritikin & Graham Barr. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 463:
Non-ASCII character seen before =encoding in '©'. Assuming CP1252