>>>>> "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