add private GBuffer type
authorRyan Lortie <desrt@desrt.ca>
Sat, 6 Feb 2010 15:18:07 +0000 (10:18 -0500)
committerRyan Lortie <desrt@desrt.ca>
Sat, 6 Feb 2010 15:18:08 +0000 (10:18 -0500)
glib/Makefile.am
glib/gbuffer.c [new file with mode: 0644]
glib/gbuffer.h [new file with mode: 0644]

index 20daa80..0f62535 100644 (file)
@@ -112,6 +112,8 @@ libglib_2_0_la_SOURCES =    \
        gbitlock.c              \
        gbookmarkfile.c         \
        gbsearcharray.h         \
+       gbuffer.c               \
+       gbuffer.h               \
        gcache.c                \
        gchecksum.c             \
        gcompletion.c           \
diff --git a/glib/gbuffer.c b/glib/gbuffer.c
new file mode 100644 (file)
index 0000000..2ab01b3
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright © 2009, 2010 Codethink Limited
+ *
+ * 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 licence, 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: Ryan Lortie <desrt@desrt.ca>
+ */
+
+#include "gbuffer.h"
+
+#include <glib/gstrfuncs.h>
+#include <glib/gatomic.h>
+#include <glib/gmem.h>
+
+#include "galias.h"
+
+typedef struct
+{
+  GBuffer buffer;
+
+  GDestroyNotify user_destroy;
+  gpointer user_data;
+} GUserNotifyBuffer;
+
+static void
+g_buffer_free_gfree (GBuffer *buffer)
+{
+  g_free ((gpointer) buffer->data);
+  g_slice_free (GBuffer, buffer);
+}
+
+/* < private >
+ * g_buffer_new_from_data:
+ * @data: the data to be used for the buffer
+ * @size: the size of @data
+ * @returns: a reference to a new #GBuffer
+ *
+ * Creates a new #GBuffer from @data.
+ *
+ * @data is copied.
+ */
+
+GBuffer *
+g_buffer_new_from_data (gconstpointer data,
+                        gsize         size)
+{
+  GBuffer *buffer;
+
+  buffer = g_slice_new (GBuffer);
+  buffer->data = g_memdup (data, size);
+  buffer->size = size;
+  buffer->free_func = g_buffer_free_gfree;
+  buffer->ref_count = 1;
+
+  return buffer;
+}
+
+/* < private >
+ * g_buffer_new_take_data:
+ * @data: the data to be used for the buffer
+ * @size: the size of @data
+ * returns: a reference to a new #GBuffer
+ *
+ * Creates a new #GBuffer from @data.
+ *
+ * @data must have been created by a call to g_malloc(), g_malloc0() or
+ * g_realloc() or by one of the many functions that wrap these calls
+ * (such as g_new(), g_strdup(), etc).
+ *
+ * After this call, @data belongs to the buffer and may no longer be
+ * modified by the caller.  g_free() will be called on @data when the
+ * buffer is no longer in use.
+ */
+GBuffer *
+g_buffer_new_take_data (gpointer data,
+                        gsize    size)
+{
+  GBuffer *buffer;
+
+  buffer = g_slice_new (GBuffer);
+  buffer->data = data;
+  buffer->size = size;
+  buffer->free_func = g_buffer_free_gfree;
+  buffer->ref_count = 1;
+
+  return buffer;
+}
+
+static void
+g_buffer_free (GBuffer *buffer)
+{
+  g_slice_free (GBuffer, buffer);
+}
+
+/* < private >
+ * g_buffer_new_from_static_data:
+ * @data: the data to be used for the buffer
+ * @size: the size of @data
+ * @returns: a reference to a new #GBuffer
+ *
+ * Creates a new #GBuffer from static data.
+ *
+ * @data must be static (ie: never modified or freed).
+ */
+GBuffer *
+g_buffer_new_from_static_data (gconstpointer data,
+                               gsize         size)
+{
+  GBuffer *buffer;
+
+  buffer = g_slice_new (GBuffer);
+  buffer->data = data;
+  buffer->size = size;
+  buffer->free_func = g_buffer_free;
+  buffer->ref_count = 1;
+
+  return buffer;
+}
+
+static void
+g_buffer_free_usernotify (GBuffer *buffer)
+{
+  GUserNotifyBuffer *ubuffer = (GUserNotifyBuffer *) buffer;
+
+  ubuffer->user_destroy (ubuffer->user_data);
+  g_slice_free (GBuffer, buffer);
+}
+
+/* < private >
+ * g_buffer_new_from_pointer:
+ * @data: the data to be used for the buffer
+ * @size: the size of @data
+ * @notify: the function to call to release the data
+ * @user_data: the data to pass to @notify
+ * @returns: a reference to a new #GBuffer
+ *
+ * Creates a #GBuffer from @data.
+ *
+ * When the last reference is dropped, @notify will be called on
+ * @user_data.
+ *
+ * @data must not be modified after this call is made, until @notify has
+ * been called to indicate that the buffer is no longer in use.
+ */
+GBuffer *
+g_buffer_new_from_pointer (gconstpointer  data,
+                           gsize          size,
+                           GDestroyNotify notify,
+                           gpointer       user_data)
+{
+  GUserNotifyBuffer *ubuffer;
+
+  ubuffer = g_slice_new (GUserNotifyBuffer);
+  ubuffer->buffer.data = data;
+  ubuffer->buffer.size = size;
+  ubuffer->buffer.free_func = g_buffer_free_usernotify;
+  ubuffer->buffer.ref_count = 1;
+  ubuffer->user_destroy = notify;
+  ubuffer->user_data = user_data;
+
+  return (GBuffer *) ubuffer;
+}
+
+/* < private >
+ * g_buffer_ref:
+ * @buffer: a #GBuffer
+ * @returns: @buffer
+ *
+ * Increase the reference count on @buffer.
+ */
+GBuffer *
+g_buffer_ref (GBuffer *buffer)
+{
+  g_atomic_int_inc (&buffer->ref_count);
+
+  return buffer;
+}
+
+/* < private >
+ * g_buffer_unref:
+ * @buffer: a #GBuffer
+ *
+ * Releases a reference on @buffer.  This may result in the buffer being
+ * freed.
+ */
+void
+g_buffer_unref (GBuffer *buffer)
+{
+  if (g_atomic_int_dec_and_test (&buffer->ref_count))
+    if (buffer->free_func != NULL)
+      buffer->free_func (buffer);
+}
diff --git a/glib/gbuffer.h b/glib/gbuffer.h
new file mode 100644 (file)
index 0000000..405904b
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright © 2009, 2010 Codethink Limited
+ *
+ * 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 licence, 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: Ryan Lortie <desrt@desrt.ca>
+ */
+
+#ifndef __G_BUFFER_H__
+#define __G_BUFFER_H__
+
+#include <glib/gtypes.h>
+
+/* < private >
+ * GBuffer:
+ * @data: a pointer to the data held in the buffer
+ * @size: the size of @data
+ *
+ * A simple refcounted data type representing a byte sequence from an
+ * unspecified origin.
+ *
+ * The purpose of a #GBuffer is to keep the memory region that it holds
+ * alive for as long as anyone holds a reference to the buffer.  When
+ * the last reference count is dropped, the memory is released.
+ *
+ * A #GBuffer can come from many different origins that may have
+ * different procedures for freeing the memory region.  Examples are
+ * memory from g_malloc(), from memory slices, from a #GMappedFile or
+ * memory from other allocators.
+ */
+typedef struct _GBuffer GBuffer;
+
+/* < private >
+ * GBufferFreeFunc:
+ * @buffer: the #GBuffer to be freed
+ *
+ * This function is provided by creators of a #GBuffer.  It is the
+ * function to be called when the reference count of @buffer drops to
+ * zero.  It should free any memory associated with the buffer and free
+ * @buffer itself.
+ */
+typedef void (* GBufferFreeFunc)                (GBuffer        *buffer);
+
+struct _GBuffer
+{
+  gconstpointer data;
+  gsize size;
+
+  /*< protected >*/
+  GBufferFreeFunc free_func;
+
+  /*< private >*/
+  gint ref_count;
+};
+
+G_GNUC_INTERNAL
+GBuffer *       g_buffer_new_from_data          (gconstpointer   data,
+                                                 gsize           size);
+G_GNUC_INTERNAL
+GBuffer *       g_buffer_new_take_data          (gpointer        data,
+                                                 gsize           size);
+G_GNUC_INTERNAL
+GBuffer *       g_buffer_new_from_static_data   (gconstpointer   data,
+                                                 gsize           size);
+G_GNUC_INTERNAL
+GBuffer *       g_buffer_new_from_pointer       (gconstpointer   data,
+                                                 gsize           size,
+                                                 GDestroyNotify  notify,
+                                                 gpointer        user_data);
+G_GNUC_INTERNAL
+GBuffer *     g_buffer_ref                      (GBuffer        *buffer);
+G_GNUC_INTERNAL
+void          g_buffer_unref                    (GBuffer        *buffer);
+
+#endif /* __G_BUFFER__H */