Standard Event Driven Object Library for D
Brian White
bcwhite at pobox.com
Wed Apr 2 23:44:53 PDT 2008
>> When doing embedded controller work, I used a very similar design for
>> passing data up a TCP/IP stack to the app. During profiling, I found
>> that a significant amount of the CPU time was being spent in the
>> dispatching of i/o events that just got ignored. By changing the
>> event handlers to say "thanks, but don't send me any more", I was able
>> to save something like 10-15% CPU time. (Profiling never shows you
>> what you expect. :-)
>
> Interesting. I suppose in GUI design, one widget will always or never
> want to handle a responsibility. You could return an enum value PassOn,
> Stop, or SendNoMore. And then the library would want to determine which
> to return, and just accept a void delegate for the event handler.
I tried using it under Windows once, setting callback functions for
various events. It worked okay, but didn't allow for multiple watchers.
I think for the GUI it's better to use a signals & slots model. It
provides more flexibility. I/O, on the other hand, usually has just one
chain of objects.
>> In the case of a C++ program in a proper operating system, think of
>> the "write" event from a select call. If you leave it active but
>> write nothing, you'll just get the event again and again and again.
>> You'll spin CPU instead of letting the OS notify you.
>>
>> There are other solutions, of course. In my C++ library, you had to
>> make a call to clear the "write callback" when you didn't want such
>> events. That would work it's way down the stack of objects until it
>> cleared the respective bit from the "write" fd_set. This ended up
>> being somewhat clumsy to implement though because objects are
>> responsible for themselves, it was never anything the library user had
>> to worry about.
>
> A bit easier to manage if you're using singletons, though that doesn't
> work in many cases. Or you could pass in whatever created the event
> along with the event data.
I always include the generator object in the call. That allows a single
object to accept from multiple sources, like an HTTPserver with multiple
open connections.
>> Instead, I thought I'd take a simpler approach of just requesting "all
>> or nothing" and letting the system take care of turning off those that
>> aren't wanted when they occurred.
>>
>> I figured it would also be beneficial to minimize the number of
>> potential loops in the object stack. If calling "DisableEvent" from
>> within an event handler, you run the risk of that method generating
>> some different event and calling back up the stack yet again. By
>> returning the status, then any other events generated aren't a loop.
>
> I've had some issues with that in the past. I don't think there is a
> simple solution. Though for GUI stuff, you could often use data binding
> for simple cases.
>
>> In the presence of a proper event queue, loops never happens because
>> the next item on the queue doesn't get processed until the previous
>> one completes. Using callbacks, however, this is not the case as
>> every "event" is always processed directly and immediately.
>
> What prevents you from adding to the queue an event that will cause this
> event to be added to the queue again?
Nothing, but there are differences. Any given event gets fully
processed before the next one. With callbacks, you can get one within
another. In the case of an event adding itself, you effectively have an
infinite loop. In the case of a callback calling itself, you have a
stack overflow.
-- Brian
More information about the Digitalmars-d
mailing list