[Tutor] Re: event-based programming

Derrick 'dman' Hudson dman@dman.ddts.net
Sat, 13 Jul 2002 01:11:33 -0500


--dWYAkE0V1FpFQHQ3
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Thu, Jul 11, 2002 at 10:43:43PM -0400, Erik Price wrote:
| I was wondering if one (or more) of the helpful geniuses on this list=20
| could help me understand how event-based programming works.

| I'm hoping someone can give me a very high-level, theoretical=20
| explanation of how this works.

At the API level, you simply write your code.  You define
functions/methods that are the "handlers" for the events you are
interested in.  Then, as Sean described, you register your even
handler with the underlying system.

Eg for a button in a GUI application :

Note - this is not real code, but it gives the idea.
It is sort of a blend of the Java/Swing and GTK+ styles of
implementaiton since those are the toolkits I've written the most code
for, though not recently.  (actually, those are the only toolkits I've
written applications for.  The two xforms labs don't really count, and
I've only glanced at wxWindows)


    import gui_system   # This is the toolkit you are using.  It could be
                        # gtk, wx, tkinter, swing, or something else.  The
                        # implementations vary, but the concept is the
                        # same.
    class MyButton( gui_system.Button ) :

        # this is the handler
        def onClick( self , event ) :
            print "I was clicked!"
            print "The event data is:", str(event)

        def __init__( self ) :
            # initialize the object, and register the handler

            # the register() method is defined by the gui system in
            # the super class 'Button'
            self.register( self.onClick , gui_system.BUTTON_CLICK_EVENT )

    # make the button
    button1 =3D MyButton()

Now the system knows that whenever the button is clicked, you want to
know about it.  It notifies you by calling the method you told it to
call.  It also provides some data about the event, such as x/y
coordinates of the mouse at the time, whether or not modifier keys (eg
Ctrl or Alt) were pressed and things like that.

Your system works because the right methods are called when an event
is "fired".  The neat thing about event-driven programming is you
don't have to worry about the low-level details.  The code you write
only has to worry about what events are relevant to what it is
supposed to do, and how to handle those events.  The events
pseudo-magically arrive and the methods are called at the right time.



The underlying system is often implmented with a main "event loop"
that polls the user interface (keyboard, mouse) for data.  When data
is recieved, it decodes it to figure out what event it corresponds to.
For example, when you click your mouse, the gui toolkit figures out
which widget is at that location on the screen.  Then it looks up the
event handlers registered for that widget and that event and calls the
methods passing it the event object.  It is this underlying even loop
which prevents the program from exiting until the "exit" button is
pressed (and the button's click handler must call the right methods to
terminate the event loop or else the only way to quit is to kill -KILL
it).



On another related note, gui applications are often multi-threaded.
If they aren't, then the event loop is effectively blocked while the
event handler is running.  That prevents any additional events from
being handled.  Either they are lost or they are queued (depends on
the system).  Have you ever seen a gui app that simply didn't respond
to anything you did and didn't repaint the screen while it was
chugging away at something?  This is why.  A common solution is to
spawn a "worker" thread to do the work while the main thread goes back
to the event loop.  This is very common in java.

This leads to another problem, though.  What if the main thread (event
loop) and the worker thread both try to update some component of the
gui at the same time?  A race condition.  Then add modal dialogs to
the picture (modal dialogs are evil anyways).  One of the bugs I fixed
at my last job (involving java/swing) was a total lockup of the gui
under certain error conditions.  The problem was just that -- a worker
thread tried to display a modal dialog.  However, it happened that
that caused a deadlock in the system (without the dialog ever
finishing painting).  The solution was quite simple -- wrap the
dialog's creation in a "Runnable" object and queue it for execution in
the main thread.  Swing has some utility functions
(eg javax.swing.SwingUtils.invokeLater()) that allow you to pass a
java.lang.Runnable object which will be added to the end of the event
queue.  Then the event loop will run() that object (call its .run()
method) in the main thread.  For a toolkit like GTK+, you will need to
make your own "main thread" and provide a queue request mechanism.
(it is quite simple to do)

An additional reason all this is necessary is because most (all?) gui
toolkits are not written to be thread-safe.  That is, they don't
provide any internal locking or synchronization; meaning that they
assume they will only be accessed from a single thread.  This is done
because locking and synchronization adds both time and memory
overhead, and for some applications it isn't necessary.  In addition,
if you follow the guidelines I outlined above (as the swing utility
functions make it fairly easy to do), you can avoid the issues
altogether and not having the speed/memory overhead is a good thing.



To summarize, event-driven programming consists of defining functions
or methods that will be called when an event occurs.  How events are
detected and handled is an implementation detail of the underlying
system.  Suffice it to be "magic" that is well documented.
Event-driven programming (at least in GUIs) tends to be seen
hand-in-hand with parallel processing, and all the synchronization
issues that entails.

HTH,
-D

--=20
=20
A mouse is a device used to point at the xterm you want to type in.
  --Kim Alm, a.s.r
=20
http://dman.ddts.net/~dman/


--dWYAkE0V1FpFQHQ3
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iEYEARECAAYFAj0vxJUACgkQO8l8XBKTpRTb4QCbB7d2dz4GN8qTZkx/mQORdzDC
VPsAoJw2tVb/uP0l7ar+MVlozdfrfd9p
=GcPg
-----END PGP SIGNATURE-----

--dWYAkE0V1FpFQHQ3--