From 3f4b7f6d37cd0036f65c31eeee033d650072561e Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Sat, 6 Feb 2010 10:18:07 -0500 Subject: [PATCH] add private GBuffer type --- glib/Makefile.am | 2 + glib/gbuffer.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ glib/gbuffer.h | 88 ++++++++++++++++++++++++ 3 files changed, 295 insertions(+) create mode 100644 glib/gbuffer.c create mode 100644 glib/gbuffer.h diff --git a/glib/Makefile.am b/glib/Makefile.am index 20daa80..0f62535 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -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 index 0000000..2ab01b3 --- /dev/null +++ b/glib/gbuffer.c @@ -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 + */ + +#include "gbuffer.h" + +#include +#include +#include + +#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 index 0000000..405904b --- /dev/null +++ b/glib/gbuffer.h @@ -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 + */ + +#ifndef __G_BUFFER_H__ +#define __G_BUFFER_H__ + +#include + +/* < 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 */ -- 2.7.4