At 1:10 PM -0400 5/11/04, Uri Guttman wrote:
 >>>>> "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
                                                                  ^^^^^
?????

Just chop that last sentence fragment out. It makes no sense. :)


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 terminology there's a bit strained, and I think it's in large part responsible for most of the rest of the confusion.


They're probably better called Named and Anonymous events, though that's a bit dodgy in some ways too. Maybe specific and generic events would be better.

The basic difference is that with Named events you *know* in advance that the event is coming because you explicitly requested it by setting a timer or making an IO request. (A specific timer or IO request, not timer or IO requests in general) This is different from things like signals as you've not asked for a particular signal to fire--they fire off whenever something outside your control and expectation happens.

Because of this, you have the event PMC for a Named event before the event occurs and thus can wait on it. You *don't* have the event PMC for an anonymous event, so you can't wait on it, all you can do is semi-generically react once it's occurred.

  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.

No, it isn't.

you say event
data there and maybe you mean event structure/object?

Nope, I mean event data. It's the data that whatever triggered the event generated.


For mouse click events it may be the X/Y/Duration of the click, for read requests it's the data read, and so on.

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).

Yes.

  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.

It isn't though. The event data is the IO data here.

  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?

You're confused here. The event handler is what throws the exception. It's the user code that's waited on the event that gets the exception. (And it's possible, though likely a bad idea, to have an exception handler make an async request and wait for it to complete)


  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.

That can't happen. You can cancel an event, but that's it. You can stop an event source, but that's different.


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

Yep.

  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?

Yes. Which doesn't do you much good if you're not in the callback... :)

  DS>    cancel Pevent

  DS> Cancel the event, if possible.

add enable/disable here.

Nope. Events aren't enable-able/disable-able.

  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?

Yes.

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.

I didn't see any reason to not do absolute times as well as deltas. It's no big deal either way.


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.

Ick. No. It's not like there's any less code there, and the intent's a bit clearer.


  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'?

Posts an event of the specified type to the event queue of the target interpreter.


 maybe call it 'check_event'? how is this different
than post_event?

No PMC handling. It means that whatever code's doing it doesn't have to manage a PMC queue (since if it's in an interrupt handler it can't allocate one--they need to be preallocated) and set up all the bits of the event PMC. Of limited utility, but for things like signal handlers that can't do much anyway and have so little information available to them it's sufficient.
--
Dan


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

Reply via email to