You got me all wrong

This is actually a mail I sent on gtk-devel-list. Obligatory disclaimer: this is not a proposal for getting gnome-vfs inside GLib, or for making GTK depend on gnome-vfs or for replacing gnome-vfs entirely; please, read on before commenting.

A while ago, on IRC, Christian Persch made the request that the monitoring of the storage file used by the GtkRecentManager could be overridden by libgnome, so that every application using the GnomeProgram API would automagically have notifications of file changes using gnome-vfs, instead of the default implementation which stat()s the file once in a while.

This spawned a more interesting discussion about how to implement a simple file monitoring API inside GLib; my approach and Christian’s were equivalent, and resolved in a new object with a vtable to be overridden per-process. Matthias, instead, suggested using a GSource, and having the file monitor to play nice with the main loop. Thus GFileMonitor was born.


The file monitoring API is as simple as the current API for idle and timeout sources:

  GSource *g_file_monitor_source_new (const gchar      *uri);
  gint     g_file_monitor_add_full   (gint              priority
                                      const gchar      *uri,
                                      GFileMonitorFunc  function,
                                      gpointer          data,
                                      GDestroyNotify    notify);
  gint     g_file_monitor_add        (const gchar      *uri,
                                      GFileMonitorFunc  function,
                                      gpointer          data);

Where GFileMonitorFunc has the signature:

  typedef gboolean (*GFileMonitorFunc) (const gchar *uri,
                                        GFileEvent   event,
                                        gpointer     data);

And works like every other GSourceFunc (continues until you return FALSE); GFileEvent is an enumeration:

  typedef enum {
  } GFileEvent;

The default implementation uses stat() for checking for file changes; it uses a quantum-based timeout delay; that is: the more time passes between one file event and the next, the more the timeout will be increased.

The nice part is that the file monitor is “pluggable” – that is, you can use another file notification mechanism (like gnome-vfs) to actually get the notification of the changes. This is done using hooks:

  typedef struct _GFileMonitorHooks GFileMonitorHooks;
  struct _GFileMonitorHooks
    gboolean (*add_monitor)    (const gchar *uri,
                                gpointer     data);
    gboolean (*cancel_monitor) (const gchar *uri,
                                gpointer     data);
    gboolean (*check_uri)      (const gchar *uri,
                                GFileEvent  *event,
                                gpointer     data);

  void g_set_file_monitor_hooks (GFileMonitorHooks *hooks,
                                 gpointer           data);

The add_monitor hook will be invoked before the source created by g_file_monitor_add() and g_file_monitor_add_full() is attached to the main loop; the cancel_monitor hook will be invoked if the callback returns FALSE; the check_uri hook is where the magic happens: it will be called at each iteration of the main loop, and will be used to check if uri has changed. The gnome-vfs implementation (attached to bug #340746) uses this hook to check for a flag inside a structure; the flag is set by the callback invoked by the GnomeVFSMonitor created inside the add_monitor hook and destroyed inside the cancel_monitor hook.


It’s important (very important: please don’t reply with “you should use gnome-vfs” – I know that, and you missed the point of this RFC) to note that this file monitoring is not intended to be more complicated than this or to replace in any way gnome-vfs; it’s useful only if you can’t depend on gnome-vfs, and for monitoring a single, local file without too much accuracy. If you need directory monitoring, more events, efficiency and remote files support, then by all means you
should use gnome-vfs.

Further improvements

A possible further enhancement would be changing the default implementation to use i-notify if it’s found at compile time, and to fall back to the stat() implementation if not (or on other platforms than linux >= 2.6.13, unless they have a native file monitoring API we could hook into).

2 Replies to “You got me all wrong”

Comments are closed.