Since events and IO are really linked, and really (kinda, sorta) the same thing, it seems silly to have two separate documents that spend half their time referring to the other, and duplicating a lot of stuff between them. (I've a hard enough time keeping things straight within a single document, let alone two)

The comments on the first draft that still apply have been incorporated in this draft. I fully expect to make a second one as there's quite a bit of IO that's still unspecified, but I wanted to get this out for folks to think about.

++++++++++++++++++++++++++Snip Here++++++++++++++++++


Events and IO =============

Parrot has a unified event and IO system--indeed events are nothing
but satisfied IO requests. (Or, alternately, IO requests are nothing
but solicited events with external data)


Basic Architecture ==================

The event and IO system revolves around streams, requests, and
events. Requests travel through streams and out the other end as
events.

Each stream in the event and IO system has the same structure. There
are zero or more pre-processing layers, a single "anchor" layer which
ultimately satisfies the request, one or more post-processing layers,
then the IO request becomes a notification that the request has been
satisfied and goes through the event handling layers.

The preprocessing, anchor, and post-processing layers are isolated
from the requesting thread, and layer code shouldn't count on access
to any information external to it. The event handling layers execute
in the context of the thread processing the event, and may count on
that thread's resources.

The system is simple--you make a request to a stream. The request
runs through the preprocessing layers which mangle it as they see
fit. The request then hits the anchor layer, which actually satisfies
the request. The anchor layer then passes the satisfied requests
through the post processing layers. When post-processing is done the
completed request is posted as an event, at which point a thread
watching the event queue will eventually process it by calling the
event layers. At this point the event is completed.

Non-IO things such as signals and OS events (assuming we can get to
them safely) behave the same way. The only difference is that the IO
request is originated by the anchor layer (which monitors the
external event source) and flows through the postprocessing and event
handling layers, but not the preprocessing layers.

At the moment each filehandle has a single set of IO layers which
handle all read, write, and command requests. This may change if it
turns out to be untenable, but split streams are a pain to keep
synchronized.

Note that any layer along the way may defer the IO request. A
deferred request stays deferred until something resumes it, at which
point it continues through the IO layers. Deferring is normally done
by the anchor layer, if it is done at all. A deferred IO request is
not considered completed and will block processing of any more events
through an IO stream if that stream guarantees ordered request
processing.

Layer and Callback functions
============================

Since IO layers and event callbacks are identical, they have the same
signature. That signature is:

   (Sreturndata, Icommand) =
          layersub(Pevent, Slayerdata, Scallbackdata, Icommand)

The returndata from a layer is passed into the next layer as its
layerdata parameter, and the returned command status is passed onto
the next layer as its command parameter. This way a layer can alter
what the next layer in the chain sees.

The commands are:

  * 1 - Event
  * 2 - Read request
  * 3 - Write request
  * 4 - Command request. The layerdata holds the command itself
  * 5 - Reset stream
  * 6 - Close stream

Negative command arguments indicate that the command request has had
an error or exception of some kind. Layers may pull out the error
or exception status to determine what they should do. A layer may
change the error status of the request by just setting it, while it
may change the exception status by throwing an exception of its
own. Requests have a single exception associated with them, the last
exception thrown by a layer in the stream.

Request/Event status
====================

Requests and events have one of the following statuses:

 * Unprocessed - The request has been issued but not yet touched
 * Preprocess - The request is in the preprocessing layers
 * Handling - The request is being dealt with by the anchor layer
 * Postprocess - The request is in the postprocessing layers
 * Completing - The request is done and waiting for event handling
 * Done - All the event handlers have run on the event
 * Historical - The event has been waited for so any pending
                exceptions have been delivered

Event/Request classes
=====================

There are two classses of events and IO requests: solicited and
unsolicited.

A solicited event or request is one that a user program has
explicitly asked for. They are unique, and are generated as a result
of user code making a request for something to happen, for example a
read from a disk file or a one-shot timer.

An unsolicited event, on the other hand, is one that parrot generates
as the result of something happening external to itself, or as the
result of some recurring event happening. Signals and GUI events, for
example, are unsolicted as are recurring timer events.

There are four big differences between solicited and unsolicited
events:

1) A solicited event goes through a stream's preprocessing
   layers. Unsolicited events and requests do not.

2) A solicted event may be cancelled from user code, as the user code
   will have the request object as soon as the request is
   made. Unsolicited events are only available to user code after the
   fact--that is, user code only knows they exist after they have
   happened.

3) A solicited event may have a callback and user data associated
   with it, an unsolicited event may not.

4) Any exception associated with a solicited event will be thrown
   when the event is waited on. An unsolicited event's exception is
   thrown as soon as the event is drained from the event queue.

Interfacing with System Events
==============================

It is possible, given the nature of fighting event loops, that parrot
may not be able to integrate its event system with the system event
loop.

Event Source Methods
====================

The following methods are required of any event source that
implements the EventSource protocol:

  pause

Stop the event source from emitting events. Any event that would be
triggered (signals, for example) are instead discarded. It is
generally considered unwise to pause event sources attached to IO devices.

  hold

Like pause, except the events are held rather than discarded.

  cancel

Permanently stop the event source.

  unpause

Undo a pause or hold on the event source. If any events are pending
because of a prior hold, those events are then posted to the even tqueue.

Event Ops
=========

The opcodes in this section are a combination of event requests and
event handling ops. It doesn't include the IO ops--those are separate.

Most of the event request ops have two forms, one of which takes a
callback PMC and user data PMC.

   checkevent

Explicitly check to see if there are any events pending in the event queue and,
if so process one.

   drainqueue

Wait forever, draining the event queue as it fills. This op only
exits if it encounters a QUEUE_DONE event in the queue.

   wait Pevent

Wait for the specified event to complete. If the event has already
completed the op doesn't wait. If there is a pending exception it is
thrown. This opcode will drain the pending event queue.

   getstat Istatus, Pevent

Returns the status of the event, noting whether it has been completed
yet and, if so, what happened.

   getdata Pdata, Pevent
   getdata Sdata, Pevent

Get the data associated with the event, if there is any.  What the data is
depends on what generated the event. (For filehandle reads this will
be the data read from the filehandle)

   getuser Puserdata, Pevent

Get the user data that was passed into this event.

   cancel Pevent

Cancel the request, if possible.

   post Pevent

Post an event to the event queue for later handling

   sethandler Ieventclass, Phandlersub

Set the default handler for the specified class of events.

   seteventlevel Ieventlevel

Set the current event level. Events of a lower level than this won't
be processed.


IO Ops ======

These are the ops that control IO. Note that the synchronous versions
of the ops are just simple wrappers around the asynchronous
versions. For example, this:

   readw mydata, Filehandle, 500

is equivalent to the sequence

   read tempevent, Filehandle, 500
   wait tempevent
   getdata mydata, tempevent

but is provided for convenience for those languages which are so
averse to asynchronous IO that they don't want to even acknowledge
its existence.


newhandle Pfilehandle, Panchorsub

Create a new filehandle. C<anchorsub> is the subroutine that anchors
the filehandle chain.

   pushhandler Pfilehandle, Phandlersub, Ireadwritecontrol

   pophandler Pfilehandle

   addhandler Pfilehandle, Phandlersub, Ioffset, Ireadwritecontrol

   removehandler Pfilehandle, Phandlersub, Ioffset, Ireadwritecontrol

   read Pevent, Pfilehandle, Ihowmuch[, Pcallback, Puserdata]

Request a read of data from the filehandle.

   readw Pdata, Pfilehandle, Ihowmuch

Synchronously read C<howmuch> data from the filehandle.

   write Pevent, Pfilehandle, Pdata[, Pcallback, Puserdata]

Write the data to the filehandle.

   writew Pfilehandle, Pdata

Synchronously write the data to the filehandle

 seek Pevent, Pfilehandle, Iwhere[, Pcallback, Puserdata]

Submit a request to seek to the specified position in the file.

 tell Pevent, Pfilehandle[, Pcallback, Puserdata]

Submit a request for the current position in the filehandle.

 un_read Pfilehandle, Pdata

Undo a read request, pushing Pdata back onto the filehandle. (Note
the _ in the op name)

--
                                        Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski                          even samurai
[EMAIL PROTECTED]                         have teddy bears and even
                                      teddy bears get drunk

Reply via email to