Brent 'Dax' Royal-Gordon wrote: > Gordon Henriksen wrote: > > >> Oh, it's worse than that—GUI commands need to be issued > from the main > >> thread, at least with OS X. (There's no actual requirement > as to which > >> thread handles the actual events as long as you treat the OS event > >> queue as the thread-unsafe thing it seems to be) Or so the > docs seem > >> to indicate, though they may be a bit conservative. > ... > > 1. Don't call it "events" so that people aren't > disappointed and > > frustrated, or > > 2. Figure out some way to fold in GUI events. > > One general-purpose Parrot event queue, plus another for the > GUI thread. > When you call a method on the GUI bindings, it really enqueues an > event for the GUI thread, which receives the message and calls the > actual method. > > Or for that matter, enqueue an event in the main queue that > only the GUI thread is interested in.
Brent, That's tantamount to fine-grained locking on a collection; instead of a mutex, an OS thread does the serialization. Fine-grained locking doesn't work. It's also going to be ridiculously slow. Can you imagine what havoc this would wreak with multiple "writers"? Not a solution. The Carbon Event Manager is (synchronously) interested in your callback's return value; if a Carbon event handler callback returns kEventNotHandled, the Event Manager may supply a default implementation. Not a solution. A GUI event simply MUST be handled from the context that the operating system or GUI toolkit called the callback; anything else is addled. This might be too large a problem, despite seemingly easy to squash into one API at the first pass. Might it help to consider breaking down and decoupling the problem for better flexibility? Here's a pass... -> class: EventData Parameter block storing information about an event that has occurred. Passed as the only argument to event handlers by convention. No intrinsic fields or operations. Subclasses: IOEventData, SignalEventData, MacMouseEventData, Win32MouseEventData, ... -> class: Event A registery of event handlers for a particular event. Defines ordering and fallback behavior and soforth, should multiple handlers be registered. Instantiate one Event for each distinguishable kind of event which can occur; handlers can then. Anonymous handlers? Not so much. How magic collections which make Events on-demand? Methods: RegisterHandler(&handler) UnregisterHandler(&handler) This API is awkward without method pointers. So add a userdata parameter; whatever, details. CallHandlers([EMAIL PROTECTED]) Synchronously calls registered handlers. Parrot's event loop would call this, as would anything which wanted to control the thread on which events were dispatched. Subclasses? Maybe to override the behavior of CallHandlers, for specialized fallback behaviors. Or perhaps to register "interest" in the event with the OS event. -> class: EventSource Something that can wake parrot's main event loop. Methods: Enable() Turn on the spigot: Register the event source with parrot's main event loop. Disable() Turn the spigot back off. Non-recurring sources (e.g., one-off timers) ought to disable themselves automatically. Subclasses: Timer, IOEventSource, SignalEventource This is all "user-mode" API, very close to the operations I'd want to see from an HLL. Adapt for C/parrot core use as appropriate. I've avoided cluttering the API by adding state variables; method pointers generally take care of that just fine. If EventData is kept naïve of Event, and Event is kept naïve of EventSource, then I think this comprises a pretty agile design. All a GUI event loop needs to do to fit in is to invoke CallHandlers(...) on an Event from a C shim. The event will be handled synchronously on that thread, and any return values necessary can be passed back in a field of the EventData. (Parameter blocks are good for both directions, after all.) Since the event loop would know the thread/interpreter, it can safely create the EventData object. For high-performance subsystems, it might be best to be able to skip the EventData if no parameters to the operation are necessary. Also consider user-mode events. A user program might want to use events to, say, signal changes in data to UI views which are displaying that data. That's probably a synchronous, rather than asynchronous, operation. All of the scary asynchronous stuff is hidden away in the EventSource and parrot's event loop. Nothing above is so intrinsically asynchronous. Which is fine. The internal event queue and runloop undoubtedly require considerable platform specialization and otherwise voodoo; "enabling" the SignalNotificationSource is undoubtedly more complex than just that. Implementation detail. They don't even appear in the design above; all user-level. (Which is not to say that these details are unnecessary.) Hope that's useful. -- Gordon Henriksen IT Manager ICLUBcentral Inc. [EMAIL PROTECTED]