nanogui: Re: Ideas on Nano-X event handeling and API (was: Re: Nano-X on X )


Previous by date: 25 Nov 1999 11:44:00 -0000 Re: Some q's, Giles Russell
Next by date: 25 Nov 1999 11:44:00 -0000 Re: Ideas on Nano-X event handeling and API (was: Re: Nano-X on X), Greg Haerr
Previous in thread: 25 Nov 1999 11:44:00 -0000 Re: Ideas on Nano-X event handeling and API (was: Re: Nano-X on X ), Greg Haerr
Next in thread: 25 Nov 1999 11:44:00 -0000 Re: Ideas on Nano-X event handeling and API (was: Re: Nano-X on X), Greg Haerr

Subject: Re: Ideas on Nano-X event handeling and API (was: Re: Nano-X on X)
From: Morten Rolland ####@####.####
Date: 25 Nov 1999 11:44:00 -0000
Message-Id: <383D2D4F.722A39D7@screenmedia.no>

Hello,

(Note: To the benefit of the rest of the list, I include the original
document at the end of this mail.)

> : Some thoughts on the event handeling architecture of Nano-X
> : and multiple main-loops in programs in general.
> : By Morten Rolland, Screen Media, ####@####.####
> 
> Morten,
>         I read your document on the event handling in Nano-X.  Actually,
> all it appears you're looking for is the ability to register other file
> descriptors in the client select() loop.

Thanks for taking the time.  I was aware of the register fd functionality
in the existing code, but I feel this is not the optimal solution.
I would probably be able to make use of the single read fd for my use, but
it doesn't solve the problem with multiple libraries with a main loop each.

I think making it possible to use nano-X as a "passive" library would be
very nice, in addition to the current method (which needs less coding but
provides less flexibility and is less orthogonal).

> When there's i/o on the fd, a GR_EVENT_TYPE_FDINPUT event
> is sent thru the GrGetNextEvent() event return.

Delivering the events like this makes it neccessary to write glue code
that interfaces to the (passive, no main loop) interface of the additional
library. More libraries will need more glue code and more headaches.

I feel it would be much to the credit of nano-X if it could be used as
a passive library as well as an active one (with its own main loop).
It would make Nano-X usable in more scenarios where the GUI system is
not considered the "most important inner loop".  Examples of this might
be applications with extreme demands on the I/O subsystem, not wanting to
pass "power-events" around inside of a high level GUI library.

>         I prefer this method, but I could as well expose portions of the
> client main loop to the programmer.  The reason I don't today is that nano-X
> isn't limited to systems running select().  We want to be able to handle
> this condition on other operating systems as well.

Yes, but having different APIs for these cases is quite OK, as other
systems may not use integers for resource handles fx, and thus require
something different from 'GsRegisterInput(int fd)' anyway.  The client app
would have to have system specific code in it anyway, if it where to wait
on its own events.  It would be really nice to have both options available!

One way to do this is to implement something similar to what I proposed (on
systems supporting select), and use that as the fundament for the standard
way of doing things (how it is done today, including GsRegisterInput), and
export the *_prepare_select and *_service functions as well to provide both?

I'd be happy to help implement it --- and it shouldn't be much work,
as long as the structure of the Nano-X client library is aimed in the
right direction, that is: One entery point in the library when there is
fresh asynchronous I/O arriving at the server socket.

Regards,
Morten Rolland

------------

Some thoughts on the event handeling architecture of Nano-X
by Morten Rolland, Screen Media, ####@####.####


Although I'm new to Nano-X and friends, I'd like to provide a wish-list
of mine for the upcomming rewrite of nano-X and its companion client
library.  This document is intended as a "food for thought" kind of
thing; I hope it holds some relevance.

I'd like to list a few basic assumptions first:

1) In an event driven system like Nano-X there must be an event loop
   that acts on arrived events.

2) We don't want to busy-wait, so we use a select (or similar) to
   sleep where possible.

3) Other parts of the application may require event loops or "main loops"
   on their own.

4) Other parts of the application may have to wait for their own
   data arriving on sockets or do non-blocking writes on pipes,
   terminals, ptys etc.

This situation is very similar to a different project of mine (not yet
released free sotware), where a flexible way to handle multiple
input/output channels was needed.

The method that was used in this project is a scheme where the application
program itself is responsible for the main-loop, and can thus call select
to wait for its own filedescriptors.

In order to let the logically independent modules or libraries "blend in"
without knowing aboaut each other, nor the main loop, we implemented a set
of functions in the various libraries that are used to initialize the file
descriptor sets used in the select call.  This is best illustrated with code:


   fd_set rfd, efd;
   struct timeval timeout, *tv;
   int maxfd, dotimeout;

   for (;;) {
       /* main loop of some application */

       maxfd = 0;       /* Zap all fd's, so libraries can insert their own */
       FD_ZERO(&rfd);
       FD_ZERO(&efd);

       dotimeout = 0;           /* Assume no timeout until told otherwize */
       timeout.tv_sec = 0;
       timeout.tv_usec = 0;

       /* This library would like to (be able to) wake up on read events,
        * and also be able to specify timeouts for the select if needed.
        */
       some_lib_prepare_select(&maxfd, &rfd, &timeout, &dotimeout);

       /* This library needs read and exception events, so we need to support
        * those as well in our own main loop (if we want to use this lib).
        */
       some_other_lib_prepare_select(&maxfd, &rfd, &efd);

       /* We may have some fd's of our own that we want to inspect */
       FD_SET(0,&rfd);

       /* Finally, make a select call based on the demands of the libraries
        * and our own program.  Make sure to do proper timeout if needed.
        */

       tv = dotimeout?(&timeout):0;
       select(maxfd+1, &rfd, (fd_set *)0, &efd, tv);

       some_lib_service_select(&rfd, tv);
       some_other_lib_service_select(&rfd, &efd);

       if ( IS_SET(0,&rfd) ) {
          do_our_own_stuff();
       }
   }

This may look complicated, but it is not really, and it is very flexible.
Much more so than the "tell main loop in library X" to "watch out for read
events on file descriptor Y" (which works ok if you are only interested
in read events and don't have another library with another main loop...)

When Nano-X gets rewritten into a more asynchronous system, I'd love to see
functionality similar to that illustrated above.  It will make it
possible to write single threded applications with a lot of simultaneous
and responsive I/O going on (like in a web browser or realtime data
visualization tool).

Personally, I need this for IPC (message passing and esp. RPC which is
asyncronously called from the "IPC main loop" which will really be
*the* main loop (with IPC support) if something similar to the proposed
system is implemented.

By having *_prepare_select functions with only the minimal number of
features needed, like a read file descriptor set and a timeout argument,
the main-loop of the program can use the minimal set of functionality needed
when calling select (ie. no write file descriptor set in above example).

For such a system to work, certain guidelines must be followed when writing
the *_prepare_select functions.  They are:

   1) Make sure to update the 'maxfd' variable (through the pointer) when
      using FD_SET on any of the fd_sets in such a way that it always holds
      the highest numbered fd of interest in the fd_sets.  Simple code
      like
                  FD_SET(my_fd,rfd);
                  if ( my_fd > *maxfd )
                     *maxfd = my_fd;

      will do the trick.

   2) Make sure the timeout value is only *reduced* (from infinity when
      *dotimeout is 0).  This means that the library functions must check
      if the current timeout value is larger than the timeout value sought
      by the library itself, and if it is, update the timeout value
      and set the *dotimeout variable.

      The application may want to use the gettimeofday function to see
      how much time has actually passed since the last time it was called,
      in case another library reduced the timeout value further.  This should
      normally not pose a problem, as "servicing" more often is OK as long
      as you don't busy wait.

   3) The service functions needs to be prepared for doing nothing, ie.
      none of its file descriptors triggers (someone elses might have, but
      it is easier and faster and cleaner to let each and every library
      see for themselves if it is time to do work.  This is kind of similar
      to hardware interrupts shared by several devices/drivers).

OK, those are my ideas on handeling the problem of multiple asynchronous I/O
streams --- I hope they may be of some value when/if revising the core parts
of the client/server protocol and libraries of Nano-X.

A plain basic main loop function call may be nice for those simple
applications that don't need any other asynchronous I/O than the
window system itself.  It will only be a small wrapper function similar to
the code above.

This way of doing things obviously gets increasingly more usefull if more
libraries where to do things this way.  Someone has to go first and lead
the way... 

Someone may have standardised this kind of problem allready for all I know...
well, so much the better.  I could use the flexibility anyway.

Previous by date: 25 Nov 1999 11:44:00 -0000 Re: Some q's, Giles Russell
Next by date: 25 Nov 1999 11:44:00 -0000 Re: Ideas on Nano-X event handeling and API (was: Re: Nano-X on X), Greg Haerr
Previous in thread: 25 Nov 1999 11:44:00 -0000 Re: Ideas on Nano-X event handeling and API (was: Re: Nano-X on X ), Greg Haerr
Next in thread: 25 Nov 1999 11:44:00 -0000 Re: Ideas on Nano-X event handeling and API (was: Re: Nano-X on X), Greg Haerr


Powered by ezmlm-browse 0.20.