>>>>> "DS" == Dan Sugalski <[EMAIL PROTECTED]> writes:

  DS> Event Classes
  DS> =============

  DS> There are two main classes of events, which we'll call expected and
  DS> unexpected.

  DS> An expected event is one that your program is specifically expecting
  DS> to get as a result of a request for asynchronous action, and each
  DS> expected event has a corresponding event handle. User code can wait
  DS> for an expected event to complete, cancel an expected event, and
  DS> query the status of an expected event. Expected events may also be
  DS> either complete or incomplete. An incomplete event is one whose
  DS> requested action hasn't yet happened, while a complete event 
                                                                  ^^^^^
?????


  DS> Unexpected events, on the other hand, happen for reasons outside of
  DS> your program. Signals, GUI events, and exceptions for asynchronous
  DS> files (which may not be delivered as signals on many platforms) are
  DS> examples of unexpected events. Unexpected events, by their nature, are
  DS> always complete, since they aren't generated until an action actually
  DS> occurs.

  DS> Some event sources may be either expected or unexpected. Network
  DS> connections are an example of this--you may have a network filehandle
  DS> set either as an expected event source, where your program must
  DS> explicitly ask for data, or set as an unexpected event source, where
  DS> a monitoring thread captures data as it is received and generates
  DS> events for the captured data.

i disagree with the two classes. how can you handle an unexpected event
without know it could happen? effectively all events are expected, some
are more expected than others. :)

the only way to get mouse movements (which is really translated to some
i/o or socket event by the windowing system) is to ask for them. same
with signals. if you don't ask to handle a signal, it uses the default
(usually IGNORE or whatever). you need a handler for each possible event
so effectively all events you can handle are expected.

  DS> Callbacks and User Data
  DS> =======================

  DS> Each expected event can have a callback routine and piece of user
  DS> data associated with it. When the event request is satisfied (The IO
  DS> operation completes or the timer fires, for example) the callback
  DS> associated with it is invoked. The user data, as well as the event
  DS> data, if there is any, is passed into the callback.

the event handle(r) itself also is passed to the callback. you say event
data there and maybe you mean event structure/object?

so let me clarify. the callback is passed the event itself, optionally
any data read for the event, and optionally any private data passed into
the event (this is usually the object or user id for this event).

  DS> Callback signatures are fixed, and of the form:

  DS>    (Preturndata, Icommandstatus) =
  DS>           callbacksub(Pevent, Peventdata, Puserdata, Icommand)

  DS> The callback is passed in the event PMC, the PMC for the event data,
  DS> and the PMC for the user data, if any. (Either or both of these can
  DS> be the Null PMC if there is no user or event data) Command is always
  DS> 0 for callback handling. (Callbacks and IO layer functions are
  DS> identical. More detail in the IO section)

how about renaming userdata to iodata since that is what it
is. eventdata could be left alone or actually renamed to userdata since
it is the data passed in to the event call and the user expects it to
come back so the code can identify the event and associate it with an
object/structure.

  DS> If a callback function throws an exception the exception itself is
  DS> deferred. Expected events defer the exception until the event is
  DS> waited on, while unexpected events throw their excecption when their
  DS> event functions are done processing. (This does mean that expected
  DS> events may have their exceptions effectively ignored if the event is
  DS> never waited on)

you need to clarify expected vs unexpected more. i wrote above they
should all be expected. i don't see how this section would change that.

  DS> Events and Exceptions
  DS> =====================

  DS> Event handlers are generally discouraged from throwing exceptions,
  DS> however it is sometimes necessary. Exceptions are handled differently
  DS> by expected and unexpected events.

  DS> With an expected event, if an event handler is terminated by an
  DS> unhandled exception, that exception is attached to the event itself,
  DS> and when user-level code C<wait>s on the event, the exception is
  DS> thrown then.

huh? if you are in an event handler, you have seen the event (and are
presumably in user level code), so why would you wait for it again?

  DS> Unexpected events whose handlers throw exceptions are handled somewhat
  DS> differently. In that case, the exception is thrown as soon as the
  DS> event is drained from the event queue. This may or may not happen
  DS> immediately, depending on how the event in question is currently being
  DS> handled. If the event is processed in a separate event handling thread
  DS> then the event is put in the main thread's event queue and the
  DS> exception will be thrown when the main thread drains the queue and
  DS> hits the event. If the event is currently being processed in the main
  DS> thread (because there is no event-handling thread, or this event
  DS> isn't being handled by one) then as soon as the event is drained from
  DS> the event queue the exception is thrown.

  DS> How events are handled
  DS> ======================

  DS> There are three steps in event handling.

  DS> First, an event is triggered. This puts the event into the event
  DS> queue, but otherwise does nothing. (This operation is interrupt-safe,
  DS> though there issues in obtaining event PMCs at interrupt level in
  DS> some cases)

  DS> Next, a queue runner pulls an event out of the event queue and calls
  DS> its handlers. These are a combination of any event class handlers as
  DS> well as an event-specific callback, if there is one. This operation
  DS> happens as normal user-level code, though it may be done
  DS> significantly after the event itself is put in the queue, and may not
  DS> happen in the same thread as the event was requested from. [NB: I'm
  DS> not sure what to do about event handling threads and shared data yet]

  DS> Finally, for expected events, something can wait on the event to get
  DS> the event's data and status. This can be done before the event has
  DS> completed, in which case the operation will wait (draining the event
  DS> queue of pending events) 

  DS> Note that the queue runner will automatically wait on any unexpected
  DS> event that it completes. This puts the event in the done state and
  DS> will throw any exception that the event handlers may have
  DS> generated. Expected events, however, will be left alone until
  DS> user-level code explicitly waits on it.

so you separate expected vs unexpected as really user level handlers vs
parrot internal handlers. why not call them all expected and
internal. only those with user level stuff get a user level callback or
wakeup on a wait. i don't see why the handling is so different.


  DS> Event States
  DS> ============

  DS> Events have five states. They are:

  DS> * Quiescent - The event object has been newly allocated but hasn't
  DS>               been associated with anything yet and can't be triggered

call that 'new' instead. or maybe disabled (but that means the event has
been associated with something already so new is better)?

  DS> * Waiting - The operation the event triggers on hasn't yet
  DS> happened

this will be confusing with the 'wait' operation. i would call it
'watching' (from event.pm) or something similar (maybe 'active' or
'enabled'?)

  DS> * Triggered - The operation the event triggers on has happened, but
  DS>               the event's handlers haven't been called yet
  DS> * Ready - The event has been processed by its handlers but hasn't yet
  DS>           been waited on to flush out any exception it might have.
  DS> * Done - The event has flushed any pending exceptions and can now
  DS>          only be queried for its status and data

you also can use a 'stopped/disabled' state. in many cases you want an active
event but stopped for a while. a good example is a write event on a
an empty socket. if enabled, it will trigger all the time since the
socket is always writeable and that will suck up the cpu. what i do is
make write events disabled by default and you enable then when you have
data to actually write. when the user space write buffer is empty you
disable the event again. this is much cleaner than creating/destroying
events.

so my state list is:

        new
        enabled
        disabled
        triggered
        ready
        done

when an event is done, who/what flushes the event itself from the
system, normal GC?

  DS>    getdata Pdata, Pevent
  DS>    getdata Sdata, Pevent

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

but won't that data already be passed in the callback? another point is
that event i/o data should be passed by reference and treated as
readonly to save copying all over the place.

  DS>    cancel Pevent

  DS> Cancel the event, if possible. 

add enable/disable here.

  DS>    settimer Pevent, Nseconds[, Pcallback, Puserdata]
  DS>    settimer Pevent, Iseconds[, Pcallback, Puserdata]

  DS> Set a timer to go off in C<seconds> seconds. 
 
  DS>    setalarm Pevent, Nabs_time[, Pcallback, Puserdata]
  DS>    setalarm Pevent, Iabs_time[, Pcallback, Puserdata]

  DS> Set a timer to go off at the absolute time specified.

  DS>    setinterval Ninterval_seconds[, Pcallback, Puserdata]
  DS>    setinterval Iinterval_seconds[, Pcallback, Puserdata]

  DS> Set an interval timer that goes off every interval_second seconds. 

are all those times (in Nseconds) are floats with fractional seconds?

i don't think there is a need for all those variants. why would alarm
need any special opcode when it is just a timer with a delay of abs_time
- NOW? let the coder handle that and lose the extra op codes.

also the interval can be folded in as a extra arg to the timer (either a
repeat flag or an interval). the initial seconds can be the first delay
and then reused for intervals or the interval value can take over:

         settimer Pevent, Idelay_seconds, Iinterval_seconds[, Pcallback,
         Puserdata]

if interval_seconds is set (>0), use it for a repeating timer. if
delay_seconds is set (>0), it is the first interval.

so now all you have is two signatures (for float or integer seconds).

you could have a mix of float delay and integer interval but that just
makes 4 signatures.

  DS> C Interface
  DS> ===========

  DS> Because many events are actually generated from within C code, the
  DS> following API is exposed for use:

  DS>   INTVAL Parrot_ping_event(Parrot_Interp Interpreter, INTVAL type);

  DS> Note that an event of type C<type> has just occurred. Returns either
  DS> 0 on success or 1 on failure. This function may fail if the target
  DS> interpreter is unable to post an event to its event queue. This
  DS> normally happens because there are no event PMCs available to
  DS> allocate for the event.

clarify. who 'notes'? maybe call it 'check_event'? how is this different
than post_event?


overall a good start. looking forward to seeing a clean fast event core.

uri

-- 
Uri Guttman  ------  [EMAIL PROTECTED]  -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs  ----------------------------  http://jobs.perl.org

Reply via email to