[% setvar title Putting an Event Loop in the Core %]

This file is part of the Perl 6 Archive

Note: these documents may be out of date. Do not use as reference!

To see what is currently happening visit http://www.perl6.org/

TITLE

Putting an Event Loop in the Core

VERSION

  Maintainer: Uri Guttman <uri@sysarch.com>
  Date: 29 Sept 2000
  Mailing List: perl6-language-flow@perl.org
  Number: 345
  Version: 1
  Status: Developing

ABSTRACT

This RFC describes a pragma and an API for an event loop and some ramifications of its implementation. We all agree that Perl needs a single event loop that can be used to multiplex I/O, signals and timers.

DESCRIPTION

Many applications need to multiplex I/O from multiple sources. The low level mechanisms (select, poll, asynchronous I/O) to support this are tricky to use. Some modules exist which help (Event.pm, IO::Select, POE, etc.) but they are not comprehensive, efficient or well integrated with Perl. There are several event loops around but the consensus is to have a single one supported in the core and used by all programs which need it.

IMPLEMENTATION

Several of us have implemented event loops in C (Nick Ing-Simmons, Joshua Pritikin, Uri Guttman) so we have plenty of experience in what need to be supported and how to code it. Since another consensus is to write the Perl I/O subsystem from scratch, then integrating a high quality event loop into it will be relatively easy.

A bigger problem is the Perl level API and semantics. First off here are the fundamental features an event loop has to support:

	Asynchronous I/O on socket, pipes, ttys and files

	Asynchronous connect/accept of sockets

	Timers and timeouts

	Safe Signals

	Plain events (executed at some future time but not timer
	delayed)

Secondly, the issue of event delivery must be addressed. I propose that events be queued using the common callback API (RFC 321) and the program has 3 choices for how to deliver them. A critical point in all dispatch methods is that they occur between Perl op codes or statements. This must happen to guarantee no collisions with memory allocations and other areas which could cause crashes and deadlocks.

	Manual Dispatch

	With manual dispatch, the code calls a function get_event which
	returns the next pending event object or undef if there are
	none. This object can then be processed by user code which may
	(Damian) switch on its type or handle it as it desires.
	This allows fine control of when events are handled, e.g. in a
	long crunching loop, you could check for events and handle them
	and then continue with the crunching. This style is meant to be
	used only be programs which need total control over their events
	dispatching.

	Event Loop

	The event loop is the traditional way to dispatch events. After
	the program intializes itself and queues up some events, it
	calls event_loop and that function takes over. Normally it never
	returns from that function unless some event cause the event
	loop to end. There can be multiple event loops active at once
	(even in a single thread) which has its (IMO) rare uses. The
	event loop code is basically a wrapper around the get_next_event
	function which gets pending events and calls their associated
	callbacks.

	Inline Dispatch

	Some programs (or coders) don't want to handle dispatching nor
	do they want to lose control to an event loop. Also some OS's
	don't support the system calls needed to do that kind of
	dispatching. Inline dispatching is for those situations. At
	designated points in the compiled program, a call is made to get
	the next event and dispatch it. The point can be every N op
	codes or between statements or some combination of that.

The coder can select the style of dispatch via a pragma. This is needed since inline dispatch affects the compiled code. I have two ideas for this praga. First it can be like this:

	use event inline => 10 ;

which will create inline dispatching every 10 opcodes. The second one is:

	use event ;

will allow use of the event loop or manual dispatch according to which call is made in the code. Either pragma must be used to enable the event subsystem otherwise all of the normal I/O will not support callbacks.

IMPACT

Current applications using the different event loops will need to be rewritten to use the Perl6 event loop.

Event dispatching has to be well integrated with how events are queued. RFC's 14 and 174 propose extended I/O functionality but they don't cover events and callbacks. My proposed Advanced I/O (AIO) will cover similar territory but encompass callbacks (RFC 321) as well. The two set of ideas need to be reconciled.

UNKNOWNS

Support for asynchronous file I/O is not universal so it will need to be faked on some systems.

I have not had enough time to cover all issues here due to the deadline but I wanted to get something on this subject in before then.

REFERENCES

Event.pm - XS based event loop module.

RFC 14: Modify open() to support FileObjects and Extensibility

RFC 47: Universal Asynchronous I/O

RFC 60: Safe Signals

RFC 174: Improved parsing and flexibility of indirect object syntax

RFC 321: Common Callback API for all AIO calls.