diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index d5a70b2e3..927d4f71f 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -2007,10 +2007,18 @@ g_win32_ftruncate gunix G_UNIX_ERROR g_unix_open_pipe +g_unix_set_fd_nonblocking + + g_unix_signal_add g_unix_signal_add_full g_unix_signal_source_new -g_unix_set_fd_nonblocking + + +GUnixFdSourceFunc +g_unix_fd_add +g_unix_fd_add_full +g_unix_fd_source_new g_unix_error_quark diff --git a/glib/glib-unix.c b/glib/glib-unix.c index 9cc27169a..0f12cc44d 100644 --- a/glib/glib-unix.c +++ b/glib/glib-unix.c @@ -284,3 +284,142 @@ g_unix_signal_add (int signum, { return g_unix_signal_add_full (G_PRIORITY_DEFAULT, signum, handler, user_data, NULL); } + +typedef struct +{ + GSource source; + + gint fd; + gpointer tag; +} GUnixFDSource; + +static gboolean +g_unix_fd_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + GUnixFDSource *fd_source = (GUnixFDSource *) source; + GUnixFDSourceFunc func = (GUnixFDSourceFunc) callback; + + if (!callback) + { + g_warning ("GUnixFDSource dispatched without callback\n" + "You must call g_source_set_callback()."); + return FALSE; + } + + return (* func) (fd_source->fd, g_source_query_unix_fd (source, fd_source->tag), user_data); +} + + +/** + * g_unix_fd_source_new: + * @fd: a file descriptor + * @condition: IO conditions to watch for on @fd + * + * Creates a #GSource to watch for a particular IO condition on a file + * descriptor. + * + * The source will never close the fd -- you must do it yourself. + * + * Returns: the newly created #GSource + * + * Since: 2.36 + **/ +GSource * +g_unix_fd_source_new (gint fd, + GIOCondition condition) +{ + static GSourceFuncs source_funcs = { + NULL, NULL, g_unix_fd_source_dispatch, NULL + }; + GUnixFDSource *fd_source; + GSource *source; + + source = g_source_new (&source_funcs, sizeof (GUnixFDSource)); + fd_source = (GUnixFDSource *) source; + + fd_source->fd = fd; + fd_source->tag = g_source_add_unix_fd (source, fd, condition); + + return source; +} + +/** + * g_unix_fd_add_full: + * @priority: the priority of the source + * @fd: a file descriptor + * @condition: IO conditions to watch for on @fd + * @function: a #GUnixFDSourceFunc + * @user_data: data to pass to @function + * @notify: function to call when the idle is removed, or %NULL + * + * Sets a function to be called when the IO condition, as specified by + * @condition becomes true for @fd. + * + * This is the same as g_unix_fd_add(), except that it allows you to + * specify a non-default priority and a provide a #GDestroyNotify for + * @user_data. + * + * Returns: the ID (greater than 0) of the event source + * + * Since: 2.36 + **/ +guint +g_unix_fd_add_full (gint priority, + gint fd, + GIOCondition condition, + GUnixFDSourceFunc function, + gpointer user_data, + GDestroyNotify notify) +{ + GSource *source; + guint id; + + g_return_val_if_fail (function != NULL, 0); + + source = g_unix_fd_source_new (fd, condition); + + if (priority != G_PRIORITY_DEFAULT) + g_source_set_priority (source, priority); + + g_source_set_callback (source, (GSourceFunc) function, user_data, notify); + id = g_source_attach (source, NULL); + g_source_unref (source); + + return id; +} + +/** + * g_unix_fd_add: + * @fd: a file descriptor + * @condition: IO conditions to watch for on @fd + * @function: a #GPollFDFunc + * @user_data: data to pass to @function + * + * Sets a function to be called when the IO condition, as specified by + * @condition becomes true for @fd. + * + * @function will be called when the specified IO condition becomes + * %TRUE. The function is expected to clear whatever event caused the + * IO condition to become true and return %TRUE in order to be notified + * when it happens again. If @function returns %FALSE then the watch + * will be cancelled. + * + * The return value of this function can be passed to g_source_remove() + * to cancel the watch at any time that it exists. + * + * The source will never close the fd -- you must do it yourself. + * + * Returns: the ID (greater than 0) of the event source + * + * Since: 2.36 + **/ +guint +g_unix_fd_add (gint fd, + GIOCondition condition, + GUnixFDSourceFunc function, + gpointer user_data) +{ + return g_unix_fd_add_full (G_PRIORITY_DEFAULT, fd, condition, function, user_data, NULL); +} diff --git a/glib/glib-unix.h b/glib/glib-unix.h index c04f66f3c..66ccf74cd 100644 --- a/glib/glib-unix.h +++ b/glib/glib-unix.h @@ -85,6 +85,39 @@ guint g_unix_signal_add (gint signum, GSourceFunc handler, gpointer user_data); +/** + * GUnixFDSourceFunc: + * @fd: the fd that triggered the event + * @condition: the IO conditions reported on @fd + * @user_data: user data passed to g_unix_fd_add() + * + * The type of functions to be called when a UNIX fd watch source + * triggers. + * + * Returns: %FALSE if the source should be removed + **/ +typedef gboolean (*GUnixFDSourceFunc) (gint fd, + GIOCondition condition, + gpointer user_data); + +GLIB_AVAILABLE_IN_2_36 +GSource *g_unix_fd_source_new (gint fd, + GIOCondition condition); + +GLIB_AVAILABLE_IN_2_36 +guint g_unix_fd_add_full (gint priority, + gint fd, + GIOCondition condition, + GUnixFDSourceFunc function, + gpointer user_data, + GDestroyNotify notify); + +GLIB_AVAILABLE_IN_2_36 +guint g_unix_fd_add (gint fd, + GIOCondition condition, + GUnixFDSourceFunc function, + gpointer user_data); + G_END_DECLS #endif /* __G_UNIX_H__ */ diff --git a/glib/glib.symbols b/glib/glib.symbols index b317e7ce7..28ddde5fd 100644 --- a/glib/glib.symbols +++ b/glib/glib.symbols @@ -1641,6 +1641,9 @@ g_unix_set_fd_nonblocking g_unix_signal_add g_unix_signal_add_full g_unix_signal_source_new +g_unix_fd_add +g_unix_fd_add_full +g_unix_fd_source_new #endif g_ascii_table g_utf8_skip