[glib/tls: 4/7] GCancellable: add g_cancellable_create_source()
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/tls: 4/7] GCancellable: add g_cancellable_create_source()
- Date: Sun, 7 Nov 2010 13:13:08 +0000 (UTC)
commit 2d26058dbfd77fdd366243c741fd3585c34e788f
Author: Dan Winship <danw gnome org>
Date: Sat Nov 6 15:49:55 2010 -0400
GCancellable: add g_cancellable_create_source()
g_cancellable_create_source() returns a GSource that triggers when its
corresponding GCancellable is cancelled. This can be used with
g_source_add_child_source() to add cancellability to a source.
Port gasynchelper's FDSource to use this rather than doing its own
cancellable handling, and also fix up its callback argument order to
be more normal.
docs/reference/gio/gio-sections.txt | 1 +
gio/gasynchelper.c | 48 ++++---------------
gio/gasynchelper.h | 4 +-
gio/gcancellable.c | 89 +++++++++++++++++++++++++++++++++++
gio/gcancellable.h | 2 +
gio/gio.symbols | 1 +
gio/giotypes.h | 15 ++++++
gio/gunixinputstream.c | 4 +-
gio/gunixoutputstream.c | 4 +-
9 files changed, 124 insertions(+), 44 deletions(-)
---
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index 1b5f84b..eda433d 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -1107,6 +1107,7 @@ g_cancellable_set_error_if_cancelled
g_cancellable_get_fd
g_cancellable_make_pollfd
g_cancellable_release_fd
+g_cancellable_create_source
g_cancellable_get_current
g_cancellable_pop_current
g_cancellable_push_current
diff --git a/gio/gasynchelper.c b/gio/gasynchelper.c
index 8e2e8e6..0f052ea 100644
--- a/gio/gasynchelper.c
+++ b/gio/gasynchelper.c
@@ -43,18 +43,14 @@ typedef struct
{
GSource source;
GPollFD pollfd;
- GCancellable *cancellable;
- gulong cancelled_tag;
} FDSource;
static gboolean
fd_source_prepare (GSource *source,
gint *timeout)
{
- FDSource *fd_source = (FDSource *)source;
*timeout = -1;
-
- return g_cancellable_is_cancelled (fd_source->cancellable);
+ return FALSE;
}
static gboolean
@@ -62,9 +58,7 @@ fd_source_check (GSource *source)
{
FDSource *fd_source = (FDSource *)source;
- return
- g_cancellable_is_cancelled (fd_source->cancellable) ||
- fd_source->pollfd.revents != 0;
+ return fd_source->pollfd.revents != 0;
}
static gboolean
@@ -78,24 +72,12 @@ fd_source_dispatch (GSource *source,
g_warn_if_fail (func != NULL);
- return (*func) (user_data, fd_source->pollfd.revents, fd_source->pollfd.fd);
+ return (*func) (fd_source->pollfd.fd, fd_source->pollfd.revents, user_data);
}
static void
fd_source_finalize (GSource *source)
{
- FDSource *fd_source = (FDSource *)source;
-
- /* we don't use g_cancellable_disconnect() here, since we are holding
- * the main context lock here, and the ::disconnect signal handler
- * will try to grab that, and deadlock looms.
- */
- if (fd_source->cancelled_tag)
- g_signal_handler_disconnect (fd_source->cancellable,
- fd_source->cancelled_tag);
-
- if (fd_source->cancellable)
- g_object_unref (fd_source->cancellable);
}
static GSourceFuncs fd_source_funcs = {
@@ -105,15 +87,6 @@ static GSourceFuncs fd_source_funcs = {
fd_source_finalize
};
-/* Might be called on another thread */
-static void
-fd_source_cancelled_cb (GCancellable *cancellable,
- gpointer data)
-{
- /* Wake up the mainloop in case we're waiting on async calls with FDSource */
- g_main_context_wakeup (NULL);
-}
-
GSource *
_g_fd_source_new (int fd,
gushort events,
@@ -125,18 +98,17 @@ _g_fd_source_new (int fd,
source = g_source_new (&fd_source_funcs, sizeof (FDSource));
fd_source = (FDSource *)source;
- if (cancellable)
- fd_source->cancellable = g_object_ref (cancellable);
-
fd_source->pollfd.fd = fd;
fd_source->pollfd.events = events;
g_source_add_poll (source, &fd_source->pollfd);
if (cancellable)
- fd_source->cancelled_tag =
- g_cancellable_connect (cancellable,
- (GCallback)fd_source_cancelled_cb,
- NULL, NULL);
-
+ {
+ GSource *cancellable_source = g_cancellable_source_new (cancellable);
+
+ g_source_add_child_source (source, cancellable_source);
+ g_source_unref (cancellable_source);
+ }
+
return source;
}
diff --git a/gio/gasynchelper.h b/gio/gasynchelper.h
index 1e65698..cd6d282 100644
--- a/gio/gasynchelper.h
+++ b/gio/gasynchelper.h
@@ -27,9 +27,9 @@
G_BEGIN_DECLS
-typedef gboolean (*GFDSourceFunc) (gpointer user_data,
+typedef gboolean (*GFDSourceFunc) (int fd,
GIOCondition condition,
- int fd);
+ gpointer user_data);
GSource *_g_fd_source_new (int fd,
gushort events,
diff --git a/gio/gcancellable.c b/gio/gcancellable.c
index 3a99532..2d8e36e 100644
--- a/gio/gcancellable.c
+++ b/gio/gcancellable.c
@@ -770,3 +770,92 @@ g_cancellable_disconnect (GCancellable *cancellable,
g_signal_handler_disconnect (cancellable, handler_id);
G_UNLOCK (cancellable);
}
+
+typedef struct {
+ GSource source;
+
+ GCancellable *cancellable;
+ GPollFD pollfd;
+} GCancellableSource;
+
+static gboolean
+cancellable_source_prepare (GSource *source,
+ gint *timeout)
+{
+ GCancellableSource *cancellable_source = (GCancellableSource *)source;
+
+ *timeout = -1;
+ return g_cancellable_is_cancelled (cancellable_source->cancellable);
+}
+
+static gboolean
+cancellable_source_check (GSource *source)
+{
+ GCancellableSource *cancellable_source = (GCancellableSource *)source;
+
+ return g_cancellable_is_cancelled (cancellable_source->cancellable);
+}
+
+static gboolean
+cancellable_source_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+{
+ GCancellableSourceFunc func = (GCancellableSourceFunc)callback;
+ GCancellableSource *cancellable_source = (GCancellableSource *)source;
+
+ return (*func) (cancellable_source->cancellable, user_data);
+}
+
+static void
+cancellable_source_finalize (GSource *source)
+{
+ GCancellableSource *cancellable_source = (GCancellableSource *)source;
+
+ if (cancellable_source->cancellable)
+ g_object_unref (cancellable_source->cancellable);
+}
+
+static GSourceFuncs cancellable_source_funcs =
+{
+ cancellable_source_prepare,
+ cancellable_source_check,
+ cancellable_source_dispatch,
+ cancellable_source_finalize
+};
+
+/**
+ * g_cancellable_source_new:
+ * @cancellable: a #GCancellable, or %NULL
+ *
+ * Creates a source that triggers if @cancellable is cancelled
+ * and calls its callback of type #GCancellableSourceFunc. This
+ * is primarily useful as a child source that can be attached to
+ * another non-cancellable source to add cancellability to it.
+ *
+ * For convenience, you can call this with a %NULL #GCancellable,
+ * in which case the source will never trigger.
+ *
+ * Return value: the new #GSource.
+ *
+ * Since: 2.28
+ */
+GSource *
+g_cancellable_source_new (GCancellable *cancellable)
+{
+ GSource *source;
+ GCancellableSource *cancellable_source;
+
+ source = g_source_new (&cancellable_source_funcs, sizeof (GCancellableSource));
+ g_source_set_name (source, "GCancellable");
+ cancellable_source = (GCancellableSource *)source;
+
+ if (g_cancellable_make_pollfd (cancellable,
+ &cancellable_source->pollfd))
+ {
+ cancellable_source->cancellable = g_object_ref (cancellable);
+ g_source_add_poll (source, &cancellable_source->pollfd);
+ }
+
+ return source;
+}
diff --git a/gio/gcancellable.h b/gio/gcancellable.h
index dc73ccd..d8fa633 100644
--- a/gio/gcancellable.h
+++ b/gio/gcancellable.h
@@ -83,6 +83,8 @@ gboolean g_cancellable_make_pollfd (GCancellable *cancellable,
GPollFD *pollfd);
void g_cancellable_release_fd (GCancellable *cancellable);
+GSource * g_cancellable_source_new (GCancellable *cancellable);
+
GCancellable *g_cancellable_get_current (void);
void g_cancellable_push_current (GCancellable *cancellable);
void g_cancellable_pop_current (GCancellable *cancellable);
diff --git a/gio/gio.symbols b/gio/gio.symbols
index eb79b70..73a41d0 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -189,6 +189,7 @@ g_cancellable_reset
g_cancellable_cancel
g_cancellable_connect
g_cancellable_disconnect
+g_cancellable_source_new
#endif
#endif
diff --git a/gio/giotypes.h b/gio/giotypes.h
index ffd38ef..829d285 100644
--- a/gio/giotypes.h
+++ b/gio/giotypes.h
@@ -376,6 +376,21 @@ typedef struct _GDBusPropertyInfo GDBusPropertyInfo;
typedef struct _GDBusInterfaceInfo GDBusInterfaceInfo;
typedef struct _GDBusNodeInfo GDBusNodeInfo;
+/**
+ * GCancellableSourceFunc:
+ * @cancellable: the #GCancellable
+ * @user_data: data passed in by the user.
+ *
+ * This is the function type of the callback used for the #GSource
+ * returned by g_cancellable_source_new().
+ *
+ * Returns: it should return %FALSE if the source should be removed.
+ *
+ * Since: 2.28
+ */
+typedef gboolean (*GCancellableSourceFunc) (GCancellable *cancellable,
+ gpointer user_data);
+
G_END_DECLS
#endif /* __GIO_TYPES_H__ */
diff --git a/gio/gunixinputstream.c b/gio/gunixinputstream.c
index 958d003..e1ee34a 100644
--- a/gio/gunixinputstream.c
+++ b/gio/gunixinputstream.c
@@ -422,9 +422,9 @@ typedef struct {
} ReadAsyncData;
static gboolean
-read_async_cb (ReadAsyncData *data,
+read_async_cb (int fd,
GIOCondition condition,
- int fd)
+ ReadAsyncData *data)
{
GSimpleAsyncResult *simple;
GError *error = NULL;
diff --git a/gio/gunixoutputstream.c b/gio/gunixoutputstream.c
index 5bc1918..a0acc31 100644
--- a/gio/gunixoutputstream.c
+++ b/gio/gunixoutputstream.c
@@ -409,9 +409,9 @@ typedef struct {
} WriteAsyncData;
static gboolean
-write_async_cb (WriteAsyncData *data,
+write_async_cb (int fd,
GIOCondition condition,
- int fd)
+ WriteAsyncData *data)
{
GSimpleAsyncResult *simple;
GError *error = NULL;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]