[glib] Add g_autofree



commit d0105f1c0845c1244c8419d0bb24c6f64ac9015f
Author: Colin Walters <walters verbum org>
Date:   Sun Feb 15 08:58:44 2015 -0500

    Add g_autofree
    
    The g_autoptr() being associated with the type name works out really
    well for things like GHashTable.  However, it's a bit more awkward to
    associate with "gchar".  Also because one can't use "char".
    Similarly, there are a lot of other "bare primitive array" types that
    one might reasonably use.
    
    This patch does not remove the autoptr for "gchar", even though I
    think it's rather awkward and strange.
    
    Also while we're here, add a test case for the cleanup bits.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=744747

 glib/docs.c              |   34 ++++++++++++++++++++++++++++++++++
 glib/glib-autocleanups.h |    8 ++++++++
 glib/gmacros.h           |    1 +
 glib/tests/Makefile.am   |    6 ++++++
 glib/tests/autoptr.c     |   37 +++++++++++++++++++++++++++++++++++++
 5 files changed, 86 insertions(+), 0 deletions(-)
---
diff --git a/glib/docs.c b/glib/docs.c
index f7a0bf2..9169d85 100644
--- a/glib/docs.c
+++ b/glib/docs.c
@@ -2423,6 +2423,40 @@
  */
 
 /**
+ * g_autofree:
+ *
+ * Macro to add an attribute to pointer variable to ensure automatic
+ * cleanup using g_free().
+ *
+ * This macro differs from g_autoptr() in that it is an attribute supplied
+ * before the type name, rather than wrapping the type definition.  Instead
+ * of using a type-specific lookup, this macro always calls g_free() directly.
+ *
+ * This means it's useful for any type that is returned from
+ * g_malloc().
+ *
+ * Otherwise, this macro has similar constraints as g_autoptr() - only
+ * supported on GCC and clang, the variable must be initialized, etc.
+ *
+ * |[
+ * gboolean
+ * operate_on_malloc_buf (void)
+ * {
+ *   g_autofree guint8* membuf = NULL;
+ *
+ *   membuf = g_malloc (8192);
+ *
+ *   /* Some computation on membuf */
+ *
+ *   /* membuf will be automatically freed here */
+ *   return TRUE;
+ * }
+ * ]|
+ *
+ * Since: 2.44
+ */
+
+/**
  * G_DEFINE_AUTOPTR_CLEANUP_FUNC:
  * @TypeName: a type name to define a g_autoptr() cleanup function for
  * @func: the cleanup function
diff --git a/glib/glib-autocleanups.h b/glib/glib-autocleanups.h
index 902e952..80d7b2b 100644
--- a/glib/glib-autocleanups.h
+++ b/glib/glib-autocleanups.h
@@ -21,6 +21,14 @@
 #error "Only <glib.h> can be included directly."
 #endif
 
+static inline void
+g_autoptr_cleanup_generic_gfree (void *p)
+{ 
+  void **pp = (void**)p;
+  if (*pp)
+    g_free (*pp);
+}
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GAsyncQueue, g_async_queue_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GBookmarkFile, g_bookmark_file_free)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GBytes, g_bytes_unref)
diff --git a/glib/gmacros.h b/glib/gmacros.h
index 62b61cb..b34cc77 100644
--- a/glib/gmacros.h
+++ b/glib/gmacros.h
@@ -402,6 +402,7 @@
   G_GNUC_END_IGNORE_DEPRECATIONS
 #define g_autoptr(TypeName) _GLIB_CLEANUP(_GLIB_AUTOPTR_FUNC_NAME(TypeName)) _GLIB_AUTOPTR_TYPENAME(TypeName)
 #define g_auto(TypeName) _GLIB_CLEANUP(_GLIB_AUTO_FUNC_NAME(TypeName)) TypeName
+#define g_autofree _GLIB_CLEANUP(g_autoptr_cleanup_generic_gfree)
 
 #else /* not GNU C */
 /* this (dummy) macro is private */
diff --git a/glib/tests/Makefile.am b/glib/tests/Makefile.am
index 445040a..bdcd0cb 100644
--- a/glib/tests/Makefile.am
+++ b/glib/tests/Makefile.am
@@ -200,6 +200,12 @@ check-am: gtester-xmllint-check
 private_LDFLAGS = @G_THREAD_LIBS@
 endif
 
+if HAVE_GCC
+test_programs += \
+       autoptr                         \
+       $(NULL)
+endif
+
 # -----------------------------------------------------------------------------
 
 if HAVE_EVENTFD
diff --git a/glib/tests/autoptr.c b/glib/tests/autoptr.c
new file mode 100644
index 0000000..b2db335
--- /dev/null
+++ b/glib/tests/autoptr.c
@@ -0,0 +1,37 @@
+#include <glib.h>
+
+static void
+test_autofree (void)
+{
+  g_autofree char *p = NULL;
+  g_autofree char *p2 = NULL;
+  g_autofree char *alwaysnull = NULL;
+
+  p = g_malloc (10);
+  p2 = g_malloc (42);
+
+  if (TRUE)
+    {
+      g_autofree guint8 *buf = g_malloc (128);
+      g_autofree char *alwaysnull_again = NULL;
+
+      buf[0] = 1;
+    }
+
+  if (TRUE)
+    {
+      g_autofree guint8 *buf2 = g_malloc (256);
+
+      buf2[255] = 42;
+    }
+}
+
+int
+main (int argc, char *argv[])
+{
+  g_test_init (&argc, &argv, NULL);
+
+  g_test_add_func ("/autoptr/autofree", test_autofree);
+
+  return g_test_run ();
+}


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