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 idea is to delay the handling of events so that they may be dispatched in priority order when it is safe for callbacks to execute.
PERL 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 or 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($result)
-
Cause all pending loop()s to return immediately. This is not implemented with
die
. It is works as ifunloop($result)
were called for all nested loops. - sweep([$max_prio])
-
Queue all pending events and dispatch any with priority strictly less than $max_prio (the highest priority is 0). The default is to process all events except idle events. (While idle events are ignored by sweep, idle watchers are not ignored. If you want to avoid triggering an idle watcher then set
max
toundef
or suspend it.) - 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 forever or until $timeout. Use of this API is not recommended because it is not efficient and does not trap exceptions.
- all_watchers()
-
Returns a list of all watchers (including stopped watchers).
- all_running()
-
Returns a list of all watchers with actively running 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( [attr1 => $value,]... );
or
use Event::type;
$w = Event::type( [attr1 => $value,]...);
Where type is substituted with the kind of watcher. Built-in types include idle, inactivity, io, signal, timer, and var.
New watchers (hopefully) have reasonable defaults and can also be customized by passing extra attributes to the constructor. When created, watcher objects are "started" and are waiting for events (see $event->start
below).
Shared Watcher Attributes
Watchers are configured with attributes (also known as properties). For example:
$watcher->cb(\&some_code); # set callback
warn $watcher->desc.": ".$watcher->hits." events happened; Wow!";
All watchers support at least the following attributes: cb, clump, hits, prio, desc, repeat, debug, and reentrant. Most watchers also offer additional attributes according to their specialty. Moreover, some attributes are only meaningful when passed via the constructor.
Shared Watcher Methods
The following methods are available for all watchers:
- $watcher->start
-
Activate the watcher. Most constructors return already active watchers.
- $watcher->again
-
This is the same as the
start
except if a watcher has special repeat behavior. For example, repeating timers recalcuate their alarm time using theinterval
parameter. - $watcher->now
-
Cause the watcher to generate an event. The callback may or may not run immediately depending upon the event's priority. If you must unconditionally invoke the callback, consider something like
$w->cb->($w);
- $watcher->stop
-
Don't look for events any more. Running events are allowed to complete but pending events are cancelled. Note that a stopped watcher can be reactivated by calling the
start
oragain
methods. - $watcher->cancel
-
Stop and destroy
$watcher
. Running events are allowed to complete but pending events are cancelled. If an attempt is made to use$watcher
after callingcancel
then an exception will be thrown. - $watcher->is_active
-
Reports whether the
$watcher
has been started. The return value is not affected by suspend. - $watcher->is_suspended
-
Reports whether the
$watcher
is suspended.
Watcher Types
- idle
-
Extra attributes: min => $seconds, max => $seconds
The callback is invoked only when no events are pending. In the callback is not triggered by idling, an event will be generated at least every
max
seconds and not more often thanmin
seconds. - inactivity
-
Extra attributes: level => $level, timeout => $seconds
Not yet documented.
- var
-
Extra attributes: var => \$var, poll => 'rw'
- timer
-
Extra attributes: at => $time, interval => $sec, hard => $bool
The
$time
and$sec
are in seconds. Fractional seconds may be used if Time::HiRes is available. The constructor also accepts anafter
attribute for easier initialization. It might be useful to know the time at the start of today. You can find it with:use Time::Local; my $TodaySeconds = int timelocal(0,0,0,(localtime)[3,4,5]);
If
interval
is set then the watcher will automatically repeat. Be aware that due to lags in the event loop, theinterval
timeout may already be in the past. If thehard
flag is set, the event will be queued for execution relative to the last time the callback was invoke. However, ifhard
is false the new timeout will be calculated relative to the current time (this is the default). - io
-
Extra attributes: fd => $fd, poll => 'rwe', got => 'rwet', [timeout => $seconds, hard => $bool]
The callback is invoked when the file descriptor,
fd
, has data to be read, written, or pending exceptions.fd
can be a GLOB, an IO::Handle object, or a file number (file descriptor).Note that it is your option whether to have multiple watchers per file handle or to use a single watcher for all event conditions.
- signal
-
Extra attribute: signal => $str
- semaphore
-
Not yet implemented.
- msg
-
Not yet implemented.
ATTRIBUTES
The following attributes currently have a meaning:
- after => $seconds
- async => $bool
-
For use in the constructor to specify a priority of -1.
- at => $time
- cb => \&code
- cb => [$class_or_object, $method_name]
-
The function or method to call when an event is dispatched. The callback is invoked with
$event
as its only argument.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. - cbtime => $time
-
When the callback was invoked most recently.
- clump => $bool
-
A watcher must somehow record if an event occurs many times before any processing can take place. Currently there are two choice. If clump is false then a new event will be generated for each occurance. On the other hand, if clump is true then each event occurance will increment
hits
. Clumping is slightly more efficient than not clumping. - 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.
- desc => $string
-
An identifying name. If this is not passed explicitly to the constructor, it will be initialized with a string that attempts to identify the location in the source code where the watcher was constructed.
- fd => $filehandle
- flags => $bits
-
The
flag
attribute encodes information about the state of an event. [XXX Fill in exact bits] [DEPRECATED?] - got => $bits
-
got
is available in the callback of watchers withpoll
.got
is in the same format aspoll
except that it gives what kind of event actually happened. In contrast,poll
is just an expression of interest. - hard => $bool
-
Determines how repeating timers are recalculated. The timer is restarted either before or after the callback depending on whether it is true or false, respectively. In long-running callbacks this can make a significant difference.
- hits => $int
-
A watcher increments
hits
every time it registers an event. This is usually only relevant ifclump
is enabled. - interval => $seconds
-
How long between repeating timeouts.
- level => $priority
- max => $seconds
-
The maximum number of seconds to wait before triggering the callback. Similar to a
timeout
. - max_cb_tm => $seconds
-
The maximum number of seconds to spend in the callback. If the callback uses more time then it is aborted. Defaults to 1 sec. This feature is normally disabled. See Event::Stats.
- min => $seconds
-
Enforce a minimum number of seconds between triggering events.
- nice => $int
-
For use in constructors to specify the offset from the default priority. All watchers have a default priority. See ${"Event::${type}::DefaultPriority"}.
- poll => $bits
-
Determines which kinds of events are of interest. This attribute can be set with either strings or bit constants. The bit constants are available via 'use Event::Watcher qw(R W E T);'.
string constant description ------ -------- --------------- 'r' R read 'w' W write 'e' E exception 't' T timeout
Thus, both of these statements enable interest in read:
$w->poll($w->poll . 'r'); $w->poll($w->poll | R);
- prio => $int
-
Priority is used to sort the event queue. 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 first.
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, they bypass the whole point of having an event queue.
Event constructors also accept
nice
as an offset from the default priority. Each type of event has a default priority. Most normal watchers default toPRIO_NORMAL
and most asyncronous watchers default toPRIO_HIGH
. Default priorities are stored in ${"Event::${type}::DefaultPriority"}. - 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. Moreover, if you keep reentering callbacks you will quickly run out of stack space. Disable this feature per watcher by setting reentrant to false. This will cause the watcher to be suspended during recursive calls tosweep
orloop
. - repeat => $bool
-
The repeat flag controls whether the callback should either be one-shot or continue waiting for new events. The default setting depends on the type of watcher. io, signal, and var default to true.
- running => $int
-
Zero if the callback is not running. Otherwise, the number of levels that the callback has been entered. This can be greater than one if a
reentrant
callback invokesloop
(or to a lesser extentsweep
). - signal => $str
-
The callback will be invoked when the specified signal is received. The $str string should be something like 'INT' or 'QUIT'. Also see the documentation for
%SIG
. - suspend => $bool
-
Don't look for events any more. Running events are allowed to complete but queued events are cancelled and subsequent pending events are ignored. Suspend should be considered a debugging tool. If you actually want to stop a watcher then use the
stop
method. - timeout => $seconds
-
The number of seconds before a watcher times out.
- var => $ref
-
A reference to the variable being watched.
Customization and Exceptions
The bulk of Event's implementation is in C for maximum performance. However, 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
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 for the duration of event processing. If an exception is detected then$Event::DIED
is invoked:$Event::DIED->($event, $@);
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 points in the optimized event processing core. Currently support hooks are detailed 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 API for callbacks written exclusively in C. 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 event loops make use of basic operating system services, the bulk of their implementation is usually outside the kernel. While an event loop may appear to do many things in parallel, it does not, even on multiprocessor hardware. Actions are always dispatched sequentially. This implies that long running callbacks must be avoided because otherwise event processing is halted.
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. While a big, complex application server is usually simpler to implement in a multithreaded fashion, a web browser can easily get by without threads. Consider a JPEG file download and render. When some new bytes are available they are sorted to the right place on the screen. Only a little state must be kept to keep track of how much has been rendered and to process subsequent incoming bytes.
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 to access or modify 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 multithreaded 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 mandate a truly multithreaded approach.
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 a particular threads implementation to see whether it 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.
WHAT ABOUT NON-PREEMPTIVE THREADS?
(Contributed by artur@vogon-solutions.com 12 Jul 1999.)
The Java language is oriented to use non-preemptive threads, yet even Java uses an event-loop for Swing (AFAIK). That is one of the reasons I don't use Java for network-centric applications. My belief is that the benefit of multi-threading is the gain in performance on SMP hardware. In my view, non-preemptive threads (java green-threads) are usually poor design. I find them harder to work with, harder to debug, and slower for a rather marginal gain in readability. I really like working with a state machine. I find it leads to more stable and better code. It also has the benefit of abstracting away how concurrency is achieved.
BUGS
The meaning of $io->timeout(0) might change. Use undef
to unset the timeout.
WHY MICROSOFT WINDOWS MIGHT BE FASTER THAN UNIX
http://www.usenix.org/events/usenix99/full_papers/banga/banga_html/index.html
ALSO SEE
Time::HiRes, Time::Warp, and NetServer::ProcessTop.
SUPPORT
If you have insights or complaints then please subscribe to the mailing list! Send email to:
majordomo@perl.org
The body of your message should read:
subscribe perl-loop
This list is archived at
http://www.xray.mpe.mpg.de/mailing-lists/perl-loop/
Thanks!
AUTHORS
Joshua N. Pritikin <bitset@mindspring.com>
Initial 0.01 implementation by Graham Barr <gbarr@pobox.com>. Other contributors include at least those lists below and folks mentioned in the ChangeLog.
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 588:
Non-ASCII character seen before =encoding in '©'. Assuming CP1252