Watching filedescriptors



One thing I and many other people regularly need is to be notified
whenever something happens on a file descriptor. This is needed when
you write networked applications, or when you with to communicated
with spawned child processes, and in many other circumstances.

The way you are supposed to do that with glib right now is with
GIOChannels. Unfortunately, GIOChannels are quite painful to use, and
somewhat overengineered.

So I propose adding this simple API for glib 2.10:

    /*
     * Watching file descriptors
     */
    typedef void (* WatchCallback) (gpointer data);
    
    void     fd_add_watch             (gint          fd,
                                       gpointer      data);
    void     fd_set_read_callback     (gint          fd,
                                       WatchCallback read_cb);
    void     fd_set_write_callback    (gint          fd,
                                       WatchCallback write_cb);
    void     fd_set_hangup_callback   (gint          fd,
                                       WatchCallback hangup_cb);
    void     fd_set_error_callback    (gint          fd,
                                       WatchCallback error_cb);
    void     fd_set_priority_callback (gint          fd,
                                       WatchCallback priority_cb);
    void     fd_remove_watch          (gint          fd);
    gboolean fd_is_watched            (gint          fd);

The way you use it is to first call fd_add_watch() with the fd you
want to watch and a pointer to a struct containing the fd. Then you
use fd_set_read_callback() to be notified whenever there is data to be
read on the fd. In the callback you will call read() on the fd, then
do whatever you need to do with the data.

If you set a callback of NULL for some event type, then the
filedescriptor won't be polled for those events.

Some notes:

        - The callbacks are not passed the filedescriptor
          separately. I have never had a need for that, because the
          application generally needs to keep the filedescriptor
          around anyway (so that it can close it). So it might as well
          just pass a pointer to the struct containing the fd.  If
          there really is no such struct, the app can use
          GINT_TO_POINTER on the fd.

        - You can only have one callback per event type per file
          descriptor. This is so that a callback of NULL can be used
          to mean "do not poll for these events", and because
          generally only one callback would call read() or write()
          anyway.

As you can tell from the copyright statement on watch.c, this is an
API that I have used for several years; it's not something I just
came up with.

The .[ch] files are available at

        http://www.daimi.au.dk/~sandmann/watch/

They need namespacing and reindenting of course.



Søren



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]