Author: allison Date: Sat Oct 13 21:02:34 2007 New Revision: 22076 Modified: trunk/docs/pdds/draft/pdd24_events.pod
Log: [pdd] The core conceptual description of the event system. Modified: trunk/docs/pdds/draft/pdd24_events.pod ============================================================================== --- trunk/docs/pdds/draft/pdd24_events.pod (original) +++ trunk/docs/pdds/draft/pdd24_events.pod Sat Oct 13 21:02:34 2007 @@ -16,78 +16,109 @@ =head1 DESCRIPTION -Description of the subject. +=over 4 -=head1 DEFINITIONS +=item - Events are objects -Definitions of important terms. (optional) +=item - Events are typed -=head1 IMPLEMENTATION +=item - Events can be fatal or non-fatal + +=item - Event handlers are code objects -[Excerpt from Perl 6 and Parrot Essentials to seed discussion.] +=item - Event handlers can be final or non-final + +=back + +=head1 DEFINITIONS An event is a notification that something has happened: the user has manipulated a GUI element, an I/O request has completed, a signal has been triggered, or a timer has expired. Most systems these days have an event handler (often two or three, which is something of a problem), because handling events is so fundamental to modern GUI programming. -Unfortunately, the event handling system is not integrated, or poorly -integrated, with the I/O system, leading to nasty code and unpleasant -workarounds to try and make a program responsive to network, file, and -GUI events simultaneously. Parrot presents a unified event handling -system, integrated with its I/O system, which makes it possible to write -cross-platform programs that work well in a complex environment. - -Parrot's events are fairly simple. An event has an event type, some -event data, an event handler, and a priority. Each thread has an event -queue, and when an event happens it's put into the right thread's -queue (or the default thread queue in those cases where we can't tell -which thread an event was destined for) to wait for something to -process it. - -Any operation that would potentially block drains the event queue -while it waits, as do a number of the cleanup opcodes that Parrot uses -to tidy up on scope exit. Parrot doesn't check each opcode for an -outstanding event for pure performance reasons, as that check gets -expensive quickly. Still, Parrot generally ensures timely event -handling, and events shouldn't sit in a queue for more than a few -milliseconds unless event handling has been explicitly disabled. - -When Parrot does extract an event from the event queue, it calls that -event's event handler, if it has one. If an event doesn't have a -handler, Parrot instead looks for a generic handler for the event type -and calls it instead. If for some reason there's no handler for the -event type, Parrot falls back to the generic event handler, which -throws an exception when it gets an event it doesn't know how to -handle. You can override the generic event handler if you want Parrot -to do something else with unhandled events, perhaps silently -discarding them instead. - -Because events are handled in mainline code, they don't have the -restrictions commonly associated with interrupt-level code. It's safe -and acceptable for an event handler to throw an exception, allocate -memory, or manipulate thread or global state safely. Event handlers -can even acquire locks if they need to, though it's not a good idea to -have an event handler blocking on lock acquisition. - -Parrot uses the priority on events for two purposes. First, the -priority is used to order the events in the event queue. Events for a -particular priority are handled in a FIFO manner, but higher-priority -events are always handled before lower-priority events. Parrot also -allows a user program or event handler to set a minimum event priority -that it will handle. If an event with a priority lower than the -current minimum arrives, it won't be handled, instead sitting in the -queue until the minimum priority level is dropped. This allows an -event handler that's dealing with a high-priority event to ignore -lower-priority events. - -User code generally doesn't need to deal with prioritized events, so -programmers should adjust event priorities with care. Adjusting the -default priority of an event, or adjusting the current minimum -priority level, is a rare occurrence. It's almost always a mistake to -change them, but the capability is there for those rare occasions -where it's the correct thing to -do. + +=head1 IMPLEMENTATION + +Parrot's event handling system is integrated with the central concurrency +scheduler. When an event is created (by a GUI element, etc), it is added to +concurrency task list. By default, events have a higher priority in the task +list than asynchronous I/O operations or threaded code operations. At +predetermined points in the execution cycle (between low-level discrete +operations for safety, behind the scenes during "blocking" operations, at the +same operational lulls where GC runs are performed, etc), the task list is +queried, and tasks are dispatched. Events are dispatched to event handlers. + +Event handlers are registered with the concurrency scheduler. When dispatching +an event, the concurrency scheduler compares the type of the event to the type +of the event handler and selects the closest match. An exact type match is +always highest ranked, then a parent type, and finally a general handler +designed to handle all types. (A parent type may be something like a category +"key press" as a parent type to "key 'a' press".) + +In the simple case, the concurrency scheduler runs within the single +interpreter thread. In more complex cases (particularly on multi-processor +machines), the concurrency scheduler runs in its own thread. In the +multi-threaded case, each individual thread may register an event handler with +the concurrency scheduler, and the event that matches the registered handler +will be dispatched to the thread that registered it. In the most complex case, +each thread runs a lightweight concurrency scheduler that coordinates with the +central scheduler (so, for example, the mini-scheduler can decide when to run +an event handler dispatched by the central scheduler). + +An event handler may mark itself as a final event handler, removing the event +from the task list, or it may be a non-final handler, leaving the event in the +task list for another thread to collect. + +Most events are non-fatal, so if a handler isn't found for them when they're +extracted from the task list, they just expire and drop out of the task list. +Events can also be fatal, in which case the interpreter will exit if a handler +isn't found (essentially the same effect as an exception). When a non-final +event handler leaves an event in the task list, it will expire if no further +relevant event handlers can be found for the event. + +The operation to query the concurrency scheduler and find if it has any tasks +to process is as cheap as possible, so it may be queried at regular intervals. + +=head2 Event API + +An event is a PMC object that contains a type, data for the event, and a +priority. + +The type of an event is only used to match the event with an event handler, but +is notionally similar to the class of an object. + +The data for the event is a PMC and could be any data passed to the event +handler by the code that originates the event. + +The priority of an event affects when it is processed by the task list. Higher +priority events are processed before lower priority events. Age is also a +relevant factor, when two events have the same priority, the older one is +processed first. An event handler or the scheduler may also be set to ignore +events below a certain threshold of priority. When the central scheduler +ignores an event because of its priority level, the event remains in the task +list until the priority threshold changes. + +=head2 Event Handler API + +An event handler contains a code object, as well as some meta information about +where it was registered. More specifically, it contains a continuation object, +capturing the full state of the interpreter where it was created. In many +cases, this has no more effect than guaranteeing that the event handler code +executes within the appropriate context of the thread that registered the +handler. + +Because events are handled in mainline code, they don't have the restrictions +commonly associated with interrupt-level code. It's safe and acceptable for an +event handler to throw an exception, allocate memory, or manipulate thread or +global state safely. Event handlers can even acquire locks if they need to, +though it's not a good idea to have an event handler blocking on lock +acquisition. + +=head2 Event Type Hierarchy + +Parrot defines a core set of event types. Users may also define their own event +types. =head2 Signals @@ -146,7 +177,9 @@ =head1 REFERENCES -http://www.seas.upenn.edu/~lipeng/homepage/unify.html + src/events.c + + http://www.seas.upenn.edu/~lipeng/homepage/unify.html =cut