Message from discussion
Event design sketch
Newsgroups: perl.perl6.internals
Path: controlnews3.google.com!news1.google.com!newsfeed.stanford.edu!nntp.perl.org
Return-Path: <d...@sidhe.org>
Mailing-List: contact perl6-internals-h...@perl.org; run by ezmlm
Delivered-To: mailing list perl6-intern...@perl.org
Received: (qmail 79468 invoked from network); 11 May 2004 18:07:06 -0000
Received: from x1.develooper.com (63.251.223.170)
by onion.develooper.com with SMTP; 11 May 2004 18:07:06 -0000
Received: (qmail 2379 invoked by uid 225); 11 May 2004 18:07:06 -0000
Delivered-To: perl6-intern...@perl.org
Received: (qmail 2373 invoked by alias); 11 May 2004 18:07:05 -0000
X-Spam-Status: No, hits=0.0 required=7.0
tests=
X-Spam-Check-By: la.mx.develooper.com
Received: from 178.94.252.64.snet.net (HELO sprite.sidhe.org) (64.252.94.178)
by la.mx.develooper.com (qpsmtpd/0.27.1) with SMTP; Tue, 11 May 2004 11:07:03 -0700
Received: (qmail 4680 invoked from network); 11 May 2004 18:05:49 -0000
X-Scanned-By: AMaViS-ng at sidhe.org
Received: from unknown (HELO ?10.0.1.3?) (d...@157.130.220.242)
by 178.94.252.64.snet.net with SMTP; 11 May 2004 18:05:44 -0000
Mime-Version: 1.0
X-Sender: dan@localhost
Message-ID: <a0610051ebcc6c23425ce@[10.0.1.3]>
In-Reply-To: <x74qqmlwk5.fsf@mail.sysarch.com>
References: <a06100519bcc6a4021201@[10.0.1.3]>
<x74qqmlwk5.fsf@mail.sysarch.com>
Date: Tue, 11 May 2004 14:06:51 -0400
To: Uri Guttman <u...@stemsystems.com>
Subject: Re: Event design sketch
Cc: perl6-intern...@perl.org
Content-Type: text/plain; charset="us-ascii" ; format="flowed"
X-Virus-Checked: Checked
X-Spam-Rating: onion.develooper.com 1.6.2 0/1000/N
Approved: n...@nntp.perl.org
From: d...@sidhe.org (Dan Sugalski)
At 1:10 PM -0400 5/11/04, Uri Guttman wrote:
> >>>>> "DS" == Dan Sugalski <d...@sidhe.org> 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
d...@sidhe.org have teddy bears and even
teddy bears get drunk