Event#

📦 max

Event - an event loop: watchers for timers, file descriptors, signals, variables, idle time, groups and custom event sources, each calling back into Perl when its event happens.

use Event qw(loop unloop);

Event->timer(after => 1, interval => 1, cb => sub { print "tick\n" });
Event->io(fd => \*STDIN, poll => 'r', cb => sub {
    my $line = <STDIN>;
    unloop() unless defined $line;
});
loop();

Each Event->TYPE(%attributes) creates a watcher and starts it (unless parked => 1). When the watched condition occurs, an event is queued at the watcher’s priority and loop runs its callback with the event as argument; $event->w is the watcher, $event->hits the number of occurrences it stands for. Watchers are stopped, restarted, suspended or cancelled with the methods of the same names.

The watcher types are Event::idle, Event::timer, Event::io, Event::var and Event::signal, which use Event loads, and Event::group and Event::generic, which are loaded with their own use. Their shared methods are Event::Watcher’s; events are Event::Event objects; Event::Watcher::Tied is the base for watcher types written in Perl.

Timers take fractional seconds when Time::HiRes is available, which use Event loads by default; use Event qw(NO_TIME_HIRES) prevents that.

Other XS modules can drive the loop from C through $Event::API (EventAPI.h, version 22), as Coro::Event does.

This is a native implementation of the CPAN module Event 1.28; its Event.pm and every Event::* module are used unchanged.

Exports#

Nothing by default. On request: time, all_watchers, all_running, all_idle, one_event, sweep, loop, unloop, unloop_all, sleep, queue, queue_pending, QUEUES, PRIO_NORMAL, PRIO_HIGH. (all_events and all_queued are listed too, but defined nowhere.)

Functions written in Perl#

From Event.pm:

  • loop() / loop($timeout) - run callbacks until unloop or unloop_all, and return the value given to it; with $timeout, stop after that many seconds, returning $timeout. Loops nest. A callback that dies does not end the loop: the error goes to $Event::DIED and the loop goes on. With no active watcher left it warns “Event: loop without active watchers” and returns.

  • sweep() / sweep($max_prio) - queue what has happened (queue_pending) and run every queued event of priority better than $max_prio, without waiting; by default all events but those of idle watchers. Errors are trapped as in loop.

  • Event->add_hooks(name => sub { ... }, ...) - Perl code run at fixed points of each round: prepare (before waiting; returns the longest time to wait), check (after waiting), asynccheck (after collecting signals), callback (before each callback). Hooks slow the loop down considerably.

  • Event::verbose_exception_handler - a $Event::DIED handler that also lists the attributes of the failing watcher.

Priorities#

Events are run in priority order, and in order of arrival within a priority. Priorities go from -1 (highest) to 6 (lowest); PRIO_HIGH is 2, PRIO_NORMAL 4, and QUEUES (7) is the number of queued priorities. An event of priority -1 is not queued: its callback runs at once, as soon as the event occurs. A watcher starts at its type’s $Event::TYPE::DefaultPriority, or PRIO_NORMAL where that is not set; only Event::signal sets it, to PRIO_HIGH. The constructor attributes nice => $offset (added to the default), async => 1 (priority -1) and prio => $level override it, prio winning over async over nice.

Customization#

  • $Event::DIED - called as $Event::DIED->($event, $error) when a callback dies inside loop or sweep; the default warns “Event: trapped error in”, the watcher’s desc and the error. The loop goes on afterwards; a handler that wants to end it can call Event::unloop_all().

  • $Event::DebugLevel - diagnostics on STDERR: from 1, why a watcher stopped when a change left it unable to generate events; from 2, each wait for events; from 3, each watcher created and the value loop returns; from 4, the errors loop traps. The finer per-watcher levels exist only when Event is built with debugging (see Event::Watcher’s debug).

Differences from upstream#

  • Event::queue checks its argument count. Called past its prototype with none, or with three or more, XS Event reads memory at random; here it dies with its usage (t/81-xs-native/Event/340-queue-arguments.t).

  • Destroying an Event::generic::Source stops the watchers still watching it; with XS Event it corrupts memory (t/81-xs-native/Event/350-source-destroyed.t; see Event::generic::Source).

Modules#

  • Event::Event - An event, as a callback receives it: one occurrence (or several, merged) of what a watcher watches.

  • Event::Watcher - The base class of every watcher: the methods and attributes all watcher types share.

  • Event::generic - A generic watcher: an event whenever Perl code says so.

  • Event::group - A group watcher: an event when none of its member watchers has run its callback for timeout seconds - a watchdog over a set of watchers.

  • Event::idle - An idle watcher: an event when the loop has nothing else to do - no event queued, nothing arriving.

  • Event::io - An io watcher: an event when a file descriptor is ready to read or to write, or has an exception pending - and, optionally, when it has been quiet for a given time.

  • Event::signal - A signal watcher: an event when the process receives a signal.

  • Event::timer - A timer watcher: an event at a given time, and optionally at every interval after it.

  • Event::var - A var watcher: an event whenever a scalar variable is written to, or read.

Functions#

Running the loop#

unloop#

unloop($result): make the innermost running loop return $result (undef when omitted), once the current callback returns.

unloop_all#

unloop_all($result): make every running loop, however deeply nested, return $result, as if unloop were called for each. It does not die.

null_loops_per_second#

null_loops_per_second($seconds): a benchmark of the system’s polling. For $seconds seconds it polls a pipe that has nothing to report, as an idle loop would, and returns how many polls one second allows.

one_event#

one_event($timeout): run one callback, waiting for an event if none is queued - at most $timeout seconds, 60 by default. Returns true if a callback ran. loop is built on it, but unlike loop it does not trap exceptions: a callback’s die propagates out of one_event.

Events#

queue#

queue($watcher), queue($watcher, $hits) or queue($watcher, $event): queue an event for the watcher - a new one of one hit, a new one of $hits hits, or $event, an event of this watcher (one of another dies “queue: event doesn’t match watcher”). The watcher need not be active. Returns nothing. Other argument counts (possible only by calling it as &Event::queue(...), past its prototype) die “Usage: Event::queue(watcher, [hits | event])”.

queue_pending#

Turn what has happened into queued events without running any callback: poll descriptors without waiting, expire due timers, and turn counted signals into events. sweep and one_event do this themselves; call it directly before pending or start to take signals that already arrived into account.

queue_time#

queue_time($prio): the latest time a callback was started for an event of priority $prio or better (0 to 6), or undef if none has been. Other priorities die “queue_time(N) out of domain [0..6]”.

Watchers#

all_watchers#

Every watcher that is not cancelled, stopped ones included, newest first.

all_idle#

The idle watchers waiting for the loop to go idle, oldest first. While the queue is busy they stay here; one with max set fires anyway when that time has passed (see Event::idle).

all_running#

The watchers whose callbacks are running, the most recently entered first; in scalar context only that one (undef when none is).

Time#

cache_time_api#

Switch Event’s clock to Time::HiRes’s, for fractional seconds; true on success, false when Time::HiRes is not loaded. use Event calls it after loading Time::HiRes, unless imported with NO_TIME_HIRES.

time#

The current time as Event sees it, in seconds since the epoch: fractional with Time::HiRes (see cache_time_api), whole seconds without. Timer times are in these units.

sleep#

sleep($seconds): block for that long, fractions included, without running the loop. Returns nothing.