[gnio] Add asynchronous initable interface



commit 2dbdac084bdfaafbf93dbd6fbbf1d30c6ca6ba17
Author: Alexander Larsson <alexl redhat com>
Date:   Thu May 7 09:50:00 2009 +0200

    Add asynchronous initable interface
    
    Similar to the GInitable interface. Useful for asynchronous
    object construction.
---
 gio/Makefile.am      |    2 +
 gio/gasyncinitable.c |  306 ++++++++++++++++++++++++++++++++++++++++++++++++++
 gio/gasyncinitable.h |  120 ++++++++++++++++++++
 3 files changed, 428 insertions(+), 0 deletions(-)

diff --git a/gio/Makefile.am b/gio/Makefile.am
index 3e50455..1381a5a 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -13,6 +13,7 @@ sources = \
 	gnio-marshal.c			\
 	gnio-marshal.h			\
 	gnioenums.c			\
+	gasyncinitable.c		\
 	ginitable.c			\
 	gsocket.c			\
 	gsocketclient.c			\
@@ -52,6 +53,7 @@ headers = \
 	gnio.h				\
 	gnioconfig.h			\
 	gnioerror.h			\
+	gasyncinitable.h		\
 	ginitable.h			\
 	gsocket.h			\
 	gsocketclient.h			\
diff --git a/gio/gasyncinitable.c b/gio/gasyncinitable.c
new file mode 100644
index 0000000..99770c4
--- /dev/null
+++ b/gio/gasyncinitable.c
@@ -0,0 +1,306 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl redhat com>
+ */
+
+#include "config.h"
+#include "gasyncinitable.h"
+#include <gio/gasyncresult.h>
+#include <gio/gsimpleasyncresult.h>
+
+/**
+ * SECTION:gasyncinitable
+ * @short_description: Asynchronously gailable object initialization interface
+ * @include: gio/gio.h
+ * @see_also: #GInitable
+ *
+ * This is the asynchronous version of #GInitable, it behaves the same
+ * in all ways except that initialization is asynchronous. For more details
+ * see the descriptions on #GInitable.
+ *
+ * A class may implement both the #GInitable and #GAsyncInitable interfaces
+ * or both.
+ *
+ * Users of objects implementing this are not intended to use
+ * the interface method directly, instead it will be used automatically
+ * in various ways. For C applications you generally just call
+ * g_async_initable_new() directly, or indirectly via a foo_thing_new_async() wrapper.
+ * This will call g_async_initable_init() under the cover, calling back with %NULL and
+ * a set %GError on failure.
+ **/
+
+static void     g_async_initable_base_init        (gpointer              g_iface);
+static void     g_async_initable_real_init_async  (GAsyncInitable       *initable,
+						   int                   io_priority,
+						   GCancellable         *cancellable,
+						   GAsyncReadyCallback   callback,
+						   gpointer              user_data);
+static gboolean g_async_initable_real_init_finish (GAsyncInitable       *initable,
+						   GAsyncResult         *res,
+						   GError              **error);
+
+GType
+g_async_initable_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      const GTypeInfo initable_info =
+      {
+	sizeof (GAsyncInitableIface), /* class_size */
+	g_async_initable_base_init,   /* base_init */
+	NULL,		/* base_finalize */
+	NULL,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+	0,
+	0,              /* n_preallocs */
+	NULL
+      };
+      GType g_define_type_id =
+	g_type_register_static (G_TYPE_INTERFACE, I_("GAsyncInitable"),
+				&initable_info, 0);
+
+      g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT);
+
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+
+static void
+g_async_initable_base_init (gpointer g_iface)
+{
+  GAsyncInitableIface *iface = g_iface;
+
+  iface->init_async = g_async_initable_real_init_async;
+  iface->init_finish = g_async_initable_real_init_finish;
+}
+
+/**
+ * g_async_initable_init_async:
+ * @initable: a #GAsyncInitable.
+ * @io_priority: the <link linkend="io-priority">I/O priority</link> 
+ *     of the operation.
+ * @cancellable: optional #GCancellable object, %NULL to ignore. 
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: the data to pass to callback function
+ *
+ * Starts asynchronous initialization of the object implementing the interface.
+ * This must be done before any real use of the object after initial construction.
+ * If the object also implements #GInitable you can optionally call g_initable_init()
+ * instead.
+ *
+ * When the initialization is finished, @callback will be called. You can then call
+ * g_async_initable_init_finish() to get the result of the initialization.
+ *
+ * Implementations may also support cancellation. If @cancellable is not %NULL,
+ * then initialization can be cancelled by triggering the cancellable object
+ * from another thread. If the operation was cancelled, the error
+ * %G_IO_ERROR_CANCELLED will be returned. If @cancellable is not %NULL and
+ * the object doesn't support cancellable initialization the error
+ * %G_IO_ERROR_NOT_SUPPORTED will be returned.
+ *
+ * If this function is not called, or returns with an error then all
+ * operations on the object should fail, generally returning the
+ * error %G_IO_ERROR_NOT_INITIALIZED.
+ *
+ * Implementations of this method must be idempotent, i.e. multiple calls
+ * to this function with the same argument should return the same results.
+ * Only the first call initializes the object, further calls return the result
+ * of the first call. This is so that its safe to implement the singleton
+ * pattern in the GObject constructor function.
+ *
+ * For classes that also support the #GInitable interface the default
+ * implementation of this method will run the g_initable_init() function
+ * in a thread, so if you want to support asynchronous initialization via
+ * threads, just implement the #GAsyncInitable interface without overriding
+ * any interface methods.
+ *
+ * Since: 2.22
+ **/
+void
+g_async_initable_init_async (GAsyncInitable     *initable,
+			     int                 io_priority,
+			     GCancellable       *cancellable,
+			     GAsyncReadyCallback callback,
+			     gpointer            user_data)
+{
+  GAsyncInitableIface *iface;
+
+  g_return_if_fail (G_IS_ASYNC_INITABLE (initable));
+
+  iface = G_ASYNC_INITABLE_GET_IFACE (initable);
+
+  return (* iface->init_async) (initable, io_priority, cancellable, callback, user_data);
+}
+
+/**
+ * g_async_initable_init_finish:
+ * @initable: a #GAsyncInitable.
+ * @res: a #GAsyncResult.
+ * @error: a #GError location to store the error occuring, or %NULL to
+ * ignore.
+ *
+ * Finishes asynchronous initialization and returns the result.
+ * See g_async_initable_init_async().
+ *
+ * Returns: %TRUE if successful. If an error
+ *     has occurred, this function will return %FALSE and set @error
+ *     appropriately if present.
+ *
+ * Since: 2.22
+ **/
+gboolean
+g_async_initable_init_finish (GAsyncInitable       *initable,
+			      GAsyncResult         *res,
+			      GError              **error)
+{
+  GAsyncInitableIface *iface;
+
+  g_return_val_if_fail (G_IS_ASYNC_INITABLE (initable), FALSE);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
+
+  if (G_IS_SIMPLE_ASYNC_RESULT (res))
+    {
+      GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+      if (g_simple_async_result_propagate_error (simple, error))
+	return FALSE;
+    }
+
+  iface = G_ASYNC_INITABLE_GET_IFACE (initable);
+
+  return (* iface->init_finish) (initable, res, error);
+}
+
+static void
+async_init_thread (GSimpleAsyncResult *res,
+		   GObject            *object,
+		   GCancellable       *cancellable)
+{
+  GError *error = NULL;
+
+  if (!g_initable_init (G_INITABLE (res), cancellable, &error))
+    {
+      g_simple_async_result_set_from_error (res, error);
+      g_error_free (error);
+    }
+}
+
+static void
+g_async_initable_real_init_async (GAsyncInitable     *initable,
+				  int                 io_priority,
+				  GCancellable       *cancellable,
+				  GAsyncReadyCallback callback,
+				  gpointer            user_data)
+{
+  GSimpleAsyncResult *res;
+
+  g_return_if_fail (G_IS_INITABLE (initable));
+
+  res = g_simple_async_result_new (G_OBJECT (initable), callback, user_data,
+				   g_async_initable_real_init_async);
+  g_simple_async_result_run_in_thread (res, async_init_thread,
+				       io_priority, cancellable);
+  g_object_unref (res);
+}
+
+static gboolean
+g_async_initable_real_init_finish (GAsyncInitable *initable,
+				   GAsyncResult *res,
+				   GError **error)
+{
+  return TRUE; /* Errors handled by base impl */
+}
+
+void
+g_async_initable_new (GType object_type,
+		      int io_priority,
+		      GCancellable  *cancellable,
+		      GAsyncReadyCallback callback,
+		      gpointer user_data,
+		      const gchar *first_property_name,
+		      ...)
+{
+  va_list var_args;
+
+  va_start (var_args, first_property_name);
+  g_async_initable_new_valist (object_type,
+			       first_property_name, var_args,
+			       io_priority, cancellable,
+			       callback, user_data);
+  va_end (var_args);
+}
+
+void
+g_async_initable_newv (GType object_type,
+		       guint n_parameters,
+		       GParameter *parameters,
+		       int io_priority,
+		       GCancellable *cancellable,
+		       GAsyncReadyCallback callback,
+		       gpointer user_data)
+{
+  GObject *obj;
+
+  g_return_if_fail (G_TYPE_IS_ASYNC_INITABLE (object_type));
+
+  obj = g_object_newv (object_type, n_parameters, parameters);
+
+  g_async_initable_init_async (G_ASYNC_INITABLE (obj),
+			       io_priority, cancellable,
+			       callback, user_data);
+}
+
+void
+g_async_initable_new_valist (GType object_type,
+			     const gchar *first_property_name,
+			     va_list var_args,
+			     int io_priority,
+			     GCancellable *cancellable,
+			     GAsyncReadyCallback callback,
+			     gpointer user_data)
+{
+  GObject *obj;
+
+  g_return_if_fail (G_TYPE_IS_ASYNC_INITABLE (object_type));
+
+  obj = g_object_new_valist (object_type,
+			     first_property_name,
+			     var_args);
+
+  g_async_initable_init_async (G_ASYNC_INITABLE (obj),
+			       io_priority, cancellable,
+			       callback, user_data);
+  g_object_unref (obj); /* Passed ownership to async call */
+}
+
+GObject *
+g_async_initable_new_finish (GAsyncInitable       *initable,
+			     GAsyncResult         *res,
+			     GError              **error)
+{
+  if (g_async_initable_init_finish (initable, res, error))
+    return g_object_ref (initable);
+  else
+    return NULL;
+}
diff --git a/gio/gasyncinitable.h b/gio/gasyncinitable.h
new file mode 100644
index 0000000..486624e
--- /dev/null
+++ b/gio/gasyncinitable.h
@@ -0,0 +1,120 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl redhat com>
+ */
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only <gio/gio.h> can be included directly."
+#endif
+
+#ifndef __G_ASYNCINITABLE_H__
+#define __G_ASYNCINITABLE_H__
+
+#include <gio/giotypes.h>
+#include <gio/ginitable.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_ASYNC_INITABLE            (g_async_initable_get_type ())
+#define G_ASYNC_INITABLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_ASYNC_INITABLE, GAsyncInitable))
+#define G_IS_ASYNC_INITABLE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_ASYNC_INITABLE))
+#define G_ASYNC_INITABLE_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_ASYNC_INITABLE, GAsyncInitableIface))
+#define G_TYPE_IS_ASYNC_INITABLE(type)   (g_type_is_a ((type), G_TYPE_ASYNC_INITABLE))
+
+/**
+ * GAsyncInitable:
+ *
+ * Interface for asynchronously initializable objects.
+ *
+ * Since: 2.22
+ **/
+typedef struct _GAsyncInitableIface GAsyncInitableIface;
+typedef struct _GAsyncInitable      GAsyncInitable;
+
+/**
+ * GAsyncInitableIface:
+ * @g_iface: The parent interface.
+ * @init_async: Starts initialization of the object.
+ * @init_finish: Finishes initialization of the object.
+ *
+ * Provides an interface for asynchronous initializing object such that
+ * initialization may fail.
+ *
+ * Since: 2.22
+ **/
+struct _GAsyncInitableIface
+{
+  GTypeInterface g_iface;
+
+  /* Virtual Table */
+
+  void     (* init_async)  (GAsyncInitable      *initable,
+			    int                  io_priority,
+			    GCancellable        *cancellable,
+			    GAsyncReadyCallback  callback,
+			    gpointer             user_data);
+  gboolean (* init_finish) (GAsyncInitable      *initable,
+			    GAsyncResult        *res,
+			    GError             **error);
+};
+
+GType    g_async_initable_get_type    (void) G_GNUC_CONST;
+
+
+void     g_async_initable_init_async  (GAsyncInitable       *initable,
+				       int                  io_priority,
+				       GCancellable         *cancellable,
+				       GAsyncReadyCallback   callback,
+				       gpointer              user_data);
+gboolean g_async_initable_init_finish (GAsyncInitable       *initable,
+				       GAsyncResult         *res,
+				       GError              **error);
+
+
+void    g_async_initable_new         (GType                 object_type,
+				      int                   io_priority,
+				      GCancellable         *cancellable,
+				      GAsyncReadyCallback   callback,
+				      gpointer              user_data,
+				      const gchar          *first_property_name,
+				       ...);
+void    g_async_initable_newv        (GType                 object_type,
+				      guint                 n_parameters,
+				      GParameter           *parameters,
+				      int                   io_priority,
+				      GCancellable         *cancellable,
+				      GAsyncReadyCallback   callback,
+				      gpointer              user_data);
+void    g_async_initable_new_valist  (GType                 object_type,
+				      const gchar          *first_property_name,
+				      va_list               var_args,
+				      int                   io_priority,
+				      GCancellable         *cancellable,
+				      GAsyncReadyCallback   callback,
+				      gpointer              user_data);
+GObject *g_async_initable_new_finish (GAsyncInitable       *initable,
+				      GAsyncResult         *res,
+				      GError              **error);
+
+
+G_END_DECLS
+
+
+#endif /* __G_ASYNCINITABLE_H__ */



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