Glib main loop update




I sat down this weekend, and did an initial implementation
of a main loop for GLib.

There are some differences from what I posted earlier:

 * It now uses a separate GSource for each timeout, idle,
   or input function. To keep things relatively efficient
   for timeouts, the main loop now passes the current
   time into the prepare() check() and dispatch() functions.

 * Registration of file events for poll() has been separated
   out a bit from the GSource API. 

 * I've built the IO watches around a GIOChannel abstraction.
   (Somewhat different from either tml's current stuff in 
   GLib, and from Josh MacDonald's proposal in the choice
   of vfuncs. Let me know what needs to be added.)

The relevant portions of the header file are below. For those who are
interested, I've put the initial implementation at:

 ftp://ftp.gtk.org/pub/users/otaylor/gmain.tar.gz

I've renamed GIOChannel to GIORiver in that tarball so
it can be compiled with current GTK+. It isn't fully debugged
yet.

Regards,
                                        Owen

[ On a different subject, what do people think about splitting
  up glib.h, which is 2200 lines before these main loop
  additions? ]

=============

typedef struct _GTimeVal GTimeVal;
typedef struct _GSourceFuncs GSourceFuncs;
typedef struct _GIOChannel GIOChannel;
typedef struct _GIOFuncs GIOFuncs;
typedef struct _GPollFD GPollFD;

/* Opaque structure */
typedef struct _GMainLoop GMainLoop;

/* Types */

struct _GTimeVal {
  glong tv_sec;
  glong tv_usec;
};

struct _GSourceFuncs {
  gboolean (*prepare)  (gpointer  source_data, 
			GTimeVal *current_time,
			gint     *timeout);
  gboolean (*check)    (gpointer  source_data,
			GTimeVal *current_time);
  gboolean (*dispatch) (gpointer  source_data, 
			GTimeVal *current_time,
			gpointer  user_data);
  GDestroyNotify destroy;
};

typedef gboolean (*GSourceFunc) (gpointer        data);



typedef enum {
  G_IO_ERROR_NONE,
  G_IO_ERROR_AGAIN,
  G_IO_ERROR_INVAL,
  G_IO_ERROR_UNKNOWN
} GIOError;

typedef enum {
  G_SEEK_CUR,
  G_SEEK_SET,
  G_SEEK_END
} GSeekType;

typedef enum {
  G_IO_IN  = POLLIN,
  G_IO_OUT = POLLOUT,
  G_IO_PRI  = POLLPRI,

  G_IO_ERR = POLLERR,
  G_IO_HUP = POLLHUP,
  G_IO_NVAL = POLLNVAL
} GIOCondition;

typedef gboolean (*GIOFunc) (GIOChannel       *source,
			     GIOCondition condition,
			     gpointer        data);

struct _GIOFuncs {
  GIOError (*io_read)   (GIOChannel *channel, 
		         gchar      *buf, 
		         guint       count,
			 guint      *bytes_read);
  GIOError (*io_write)  (GIOChannel *channel, 
		 	 gchar      *buf, 
			 guint       count,
			 guint      *bytes_written);
  GIOError (*io_seek)   (GIOChannel   *channel, 
		 	 gint        offset, 
		  	 GSeekType   type);
  void (*io_close)      (GIOChannel *channel);
  guint (*io_add_watch) (GIOChannel      *channel,
			 gint           priority,
			 GIOCondition   condition,
			 GIOFunc        func,
			 gpointer       user_data,
			 GDestroyNotify notify);
  GDestroyNotify io_free;
};

struct _GIOChannel {
  gpointer channel_data;
};

struct _GPollFD {
   gint fd;
   gushort events;
   gushort revents;
};

typedef gint (*GPollFunc) (GPollFD *ufds, guint nfsd, gint timeout);

/* Hooks for adding to the main loop */

guint g_source_add                  (gint           priority, 
				     GSourceFuncs  *funcs,
				     gpointer       source_data, 
				     gpointer       user_data,
				     GDestroyNotify notify);
void g_source_remove                (guint          tag);
void g_source_remove_by_user_data   (gpointer       user_data);
void g_source_remove_by_source_data (gpointer       source_data);


void g_get_current_time (GTimeVal *result);

/* Running the main loop */

GMainLoop *g_main_new (void);
void g_main_run (GMainLoop *loop);
void g_main_quit (GMainLoop *loop);
void g_main_destroy (GMainLoop *loop);

/* Run a single iteration of the mainloop. If block is FALSE,
 * will never block
 */
void g_main_iteration (gboolean block);

/* See if any events are pending
 */
gboolean g_main_pending ();




/********************************/

/* Low level unix-centric file poll framework */

GPollFD *g_main_poll_add      (gint   priority, 
			       gint   fd, 
			       gshort events);
void     g_main_poll_remove   (GPollFD *fd);

void     g_main_set_poll_func (GPollFunc func);

 
/***************
 * IO Channels *
 ***************/

GIOChannel *g_io_channel_new    (GIOFuncs      *funcs,
			         gpointer       channel_data);
void      g_io_channel_ref      (GIOChannel    *channel);
void      g_io_channel_unref    (GIOChannel    *channel);
GIOError  g_io_channel_read     (GIOChannel    *channel, 
			         gchar         *buf, 
			         guint          count,
			         guint         *bytes_read);
GIOError  g_io_channel_write    (GIOChannel    *channel, 
			         gchar         *buf, 
			         guint          count,
			         guint         *bytes_written);
GIOError  g_io_channel_seek     (GIOChannel    *channel,
			         gint           offset, 
			         GSeekType      type);
void      g_io_channel_close    (GIOChannel    *channel);
guint     g_io_add_watch_full   (GIOChannel    *channel,
			         gint           priority,
			         GIOCondition   condition,
			         GIOFunc        func,
			         gpointer       user_data,
			         GDestroyNotify notify);
guint    g_io_add_watch         (GIOChannel    *channel,
			         GIOCondition   condition,
			         GIOFunc        func,
			         gpointer       user_data);

GIOChannel *g_io_channel_unix_new    (int       fd);
gint        g_io_channel_unix_get_fd (GIOChannel *channel);

/* GIOChannel *g_io_std_new (FILE *file); */

/**********************
 * Idles and timeouts *
 **********************/

guint g_timeout_add_full      (gint           priority,
			       guint          interval, 
			       GSourceFunc    function,
			       gpointer       data,
			       GDestroyNotify notify);
guint g_timeout_add           (guint          interval,
			       GSourceFunc    function,
			       gpointer       data);

guint	   g_idle_add		 (GSourceFunc          function,
				  gpointer	       data);
guint	   g_idle_add_full       (gint   	       priority,
				  GSourceFunc	       function,
				  gpointer	       data,
				  GDestroyNotify       destroy);



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