mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-09-27 17:52:58 +02:00
Add reference counted memory areas
A lot of our data structures are reference counted these days. It can be useful to allow creating reference counted data without necessarily duplicating all the reference counting machinery — a field in the struct, reference and unreference functions, a GDestroyNotify-compatible function for destroying the contents. We can re-use the same overallocation and pointer offset trick we use when allocating a GTypeInstance in gobject, and add all the reference counting meta-information directly on top of the allocation size. https://bugzilla.gnome.org/show_bug.cgi?id=622721
This commit is contained in:
@@ -55,6 +55,7 @@
|
|||||||
<xi:include href="xml/modules.xml" />
|
<xi:include href="xml/modules.xml" />
|
||||||
<xi:include href="xml/memory.xml" />
|
<xi:include href="xml/memory.xml" />
|
||||||
<xi:include href="xml/memory_slices.xml" />
|
<xi:include href="xml/memory_slices.xml" />
|
||||||
|
<xi:include href="xml/refcount.xml" />
|
||||||
<xi:include href="xml/iochannels.xml" />
|
<xi:include href="xml/iochannels.xml" />
|
||||||
<xi:include href="xml/error_reporting.xml" />
|
<xi:include href="xml/error_reporting.xml" />
|
||||||
<xi:include href="xml/warnings.xml" />
|
<xi:include href="xml/warnings.xml" />
|
||||||
|
@@ -1016,6 +1016,30 @@ glib_mem_profiler_table
|
|||||||
g_mem_profile
|
g_mem_profile
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>refcount</FILE>
|
||||||
|
g_ref_pointer_new
|
||||||
|
g_ref_pointer_new0
|
||||||
|
|
||||||
|
<SUBSECTION>
|
||||||
|
g_ref_pointer_alloc
|
||||||
|
g_ref_pointer_alloc0
|
||||||
|
g_ref_pointer_take
|
||||||
|
|
||||||
|
<SUBSECTION>
|
||||||
|
g_ref_pointer_make_atomic
|
||||||
|
|
||||||
|
<SUBSECTION>
|
||||||
|
g_ref_pointer_acquire
|
||||||
|
g_ref_pointer_release
|
||||||
|
|
||||||
|
<SUBSECTION>
|
||||||
|
g_ref_count_init
|
||||||
|
g_ref_count_inc
|
||||||
|
g_ref_count_dec
|
||||||
|
g_ref_count_make_atomic
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<TITLE>Warnings and Assertions</TITLE>
|
<TITLE>Warnings and Assertions</TITLE>
|
||||||
<FILE>warnings</FILE>
|
<FILE>warnings</FILE>
|
||||||
|
@@ -153,6 +153,7 @@ libglib_2_0_la_SOURCES = \
|
|||||||
gquark.c \
|
gquark.c \
|
||||||
gqueue.c \
|
gqueue.c \
|
||||||
grand.c \
|
grand.c \
|
||||||
|
gref.c \
|
||||||
gregex.c \
|
gregex.c \
|
||||||
gscanner.c \
|
gscanner.c \
|
||||||
gscripttable.h \
|
gscripttable.h \
|
||||||
@@ -285,6 +286,7 @@ glibsubinclude_HEADERS = \
|
|||||||
gquark.h \
|
gquark.h \
|
||||||
gqueue.h \
|
gqueue.h \
|
||||||
grand.h \
|
grand.h \
|
||||||
|
gref.h \
|
||||||
gregex.h \
|
gregex.h \
|
||||||
gscanner.h \
|
gscanner.h \
|
||||||
gsequence.h \
|
gsequence.h \
|
||||||
|
@@ -69,6 +69,7 @@
|
|||||||
#include <glib/gquark.h>
|
#include <glib/gquark.h>
|
||||||
#include <glib/gqueue.h>
|
#include <glib/gqueue.h>
|
||||||
#include <glib/grand.h>
|
#include <glib/grand.h>
|
||||||
|
#include <glib/gref.h>
|
||||||
#include <glib/gregex.h>
|
#include <glib/gregex.h>
|
||||||
#include <glib/gscanner.h>
|
#include <glib/gscanner.h>
|
||||||
#include <glib/gsequence.h>
|
#include <glib/gsequence.h>
|
||||||
|
464
glib/gref.c
Normal file
464
glib/gref.c
Normal file
@@ -0,0 +1,464 @@
|
|||||||
|
/* gref.h: Reference counted memory areas
|
||||||
|
*
|
||||||
|
* Copyright 2015 Emmanuele Bassi
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:refcount
|
||||||
|
* @short_description: reference counted memory areas
|
||||||
|
* @title: References
|
||||||
|
*
|
||||||
|
* These functions provide support for allocating and freeing reference
|
||||||
|
* counted memory areas.
|
||||||
|
*
|
||||||
|
* Reference counted memory areas are kept alive as long as something holds
|
||||||
|
* a reference on them; as soon as their reference count drops to zero, the
|
||||||
|
* associated memory is freed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "glibconfig.h"
|
||||||
|
|
||||||
|
#include "gref.h"
|
||||||
|
|
||||||
|
#include "gatomic.h"
|
||||||
|
#include "gconstructor.h"
|
||||||
|
#include "gmessages.h"
|
||||||
|
#include "gtestutils.h"
|
||||||
|
#include "valgrind.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_ref_count_init:
|
||||||
|
* @refcount: a pointer to an integer used for reference counting
|
||||||
|
* @atomic: whether reference counting should be atomic
|
||||||
|
*
|
||||||
|
* Initializes a reference counting value.
|
||||||
|
*
|
||||||
|
* Since: 2.44
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_ref_count_init (volatile int *refcount,
|
||||||
|
gboolean atomic)
|
||||||
|
{
|
||||||
|
*refcount = atomic ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_ref_count_inc:
|
||||||
|
* @refcount: a pointer to an integer used for reference counting
|
||||||
|
*
|
||||||
|
* Increases a reference counter, using atomic operations if needed.
|
||||||
|
*
|
||||||
|
* Since: 2.44
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_ref_count_inc (volatile int *refcount)
|
||||||
|
{
|
||||||
|
int refs;
|
||||||
|
|
||||||
|
test_again:
|
||||||
|
refs = *refcount;
|
||||||
|
|
||||||
|
if (refs > 0)
|
||||||
|
*refcount += 1;
|
||||||
|
else if (G_UNLIKELY (!g_atomic_int_compare_and_exchange (refcount, refs, refs - 1)))
|
||||||
|
goto test_again;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_ref_count_dec:
|
||||||
|
* @refcount: a pointer to an integer used for reference counting
|
||||||
|
*
|
||||||
|
* Decreases a reference counter, using atomic operations if needed.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the reference counter hit zero
|
||||||
|
*
|
||||||
|
* Since: 2.44
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
g_ref_count_dec (volatile int *refcount)
|
||||||
|
{
|
||||||
|
int refs;
|
||||||
|
|
||||||
|
test_again:
|
||||||
|
refs = *refcount;
|
||||||
|
if (refs == -1 || refs == 1)
|
||||||
|
return TRUE;
|
||||||
|
if (refs > 0)
|
||||||
|
*refcount -= 1;
|
||||||
|
else if (G_UNLIKELY (!g_atomic_int_compare_and_exchange (refcount, refs, refs + 1)))
|
||||||
|
goto test_again;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_ref_count_make_atomic:
|
||||||
|
* @refcount: a pointer to an integer used for reference counting
|
||||||
|
*
|
||||||
|
* Changes the reference counting semantics of a reference counter to
|
||||||
|
* be atomic if they weren't.
|
||||||
|
*
|
||||||
|
* Since: 2.44
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_ref_count_make_atomic (volatile int *refcount)
|
||||||
|
{
|
||||||
|
int refs = g_atomic_int_get (refcount);
|
||||||
|
|
||||||
|
if (refs > 0)
|
||||||
|
*refcount = -refs;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define STRUCT_ALIGNMENT (2 * sizeof (gsize))
|
||||||
|
#define ALIGN_STRUCT(offset) ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT)
|
||||||
|
|
||||||
|
#define G_REF_PTR_SIZE sizeof (GRefPtr)
|
||||||
|
#define G_REF_PTR(ptr) (GRefPtr *) (((char *) (ptr)) - G_REF_PTR_SIZE)
|
||||||
|
|
||||||
|
typedef struct _GRefPtr GRefPtr;
|
||||||
|
|
||||||
|
struct _GRefPtr
|
||||||
|
{
|
||||||
|
volatile int ref_count;
|
||||||
|
|
||||||
|
gsize alloc_size;
|
||||||
|
|
||||||
|
GDestroyNotify notify;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef G_ENABLE_DEBUG
|
||||||
|
#include "ghash.h"
|
||||||
|
#include "gthread.h"
|
||||||
|
|
||||||
|
static GHashTable *referenced_pointers;
|
||||||
|
G_LOCK_DEFINE_STATIC (referenced_pointers);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
g_ref_pointer_register (gpointer ref)
|
||||||
|
{
|
||||||
|
G_LOCK (referenced_pointers);
|
||||||
|
if (G_UNLIKELY (referenced_pointers == NULL))
|
||||||
|
referenced_pointers = g_hash_table_new (NULL, NULL);
|
||||||
|
|
||||||
|
g_hash_table_add (referenced_pointers, ref);
|
||||||
|
G_UNLOCK (referenced_pointers);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
g_ref_pointer_unregister (gpointer ref)
|
||||||
|
{
|
||||||
|
G_LOCK (referenced_pointers);
|
||||||
|
if (G_LIKELY (referenced_pointers != NULL))
|
||||||
|
g_hash_table_remove (referenced_pointers, ref);
|
||||||
|
G_UNLOCK (referenced_pointers);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
g_is_ref_pointer (gconstpointer ref)
|
||||||
|
{
|
||||||
|
gboolean res = FALSE;
|
||||||
|
|
||||||
|
G_LOCK (referenced_pointers);
|
||||||
|
if (G_LIKELY (referenced_pointers != NULL))
|
||||||
|
res = g_hash_table_contains (referenced_pointers, ref);
|
||||||
|
G_UNLOCK (referenced_pointers);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA
|
||||||
|
#pragma G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(glib_ref_pointers_clear)
|
||||||
|
#endif
|
||||||
|
G_DEFINE_DESTRUCTOR(glib_ref_pointers_clear)
|
||||||
|
|
||||||
|
static void
|
||||||
|
glib_ref_pointers_clear (void)
|
||||||
|
{
|
||||||
|
if (referenced_pointers != NULL)
|
||||||
|
g_hash_table_unref (referenced_pointers);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* G_ENABLE_DEBUG */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_ref_pointer_new:
|
||||||
|
* @Type: the type to allocate
|
||||||
|
* @free_func: the free function
|
||||||
|
*
|
||||||
|
* Allocates a reference counted memory area corresponding to @Type.
|
||||||
|
*
|
||||||
|
* See also: g_ref_pointer_alloc()
|
||||||
|
*
|
||||||
|
* Returns: the newly allocated memory area
|
||||||
|
*
|
||||||
|
* Since: 2.44
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_ref_pointer_new0:
|
||||||
|
* @Type: the type to allocate
|
||||||
|
* @free_func: the free function
|
||||||
|
*
|
||||||
|
* Allocates and clears a reference counted memory area corresponding
|
||||||
|
* to @Type.
|
||||||
|
*
|
||||||
|
* See also: g_ref_pointer_alloc0()
|
||||||
|
*
|
||||||
|
* Returns: the newly allocated memory area
|
||||||
|
*
|
||||||
|
* Since: 2.44
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* g_ref_pointer_destroy:
|
||||||
|
* @ref: a reference counted memory area
|
||||||
|
*
|
||||||
|
* Forces the destruction of a reference counter memory area.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
g_ref_pointer_destroy (gpointer ref)
|
||||||
|
{
|
||||||
|
GRefPtr *real = G_REF_PTR (ref);
|
||||||
|
gsize alloc_size = real->alloc_size;
|
||||||
|
gsize private_size = G_REF_PTR_SIZE;
|
||||||
|
char *allocated = ((char *) ref) - private_size;
|
||||||
|
|
||||||
|
if (real->notify != NULL)
|
||||||
|
real->notify (ref);
|
||||||
|
|
||||||
|
#ifdef G_ENABLE_DEBUG
|
||||||
|
g_ref_pointer_unregister (ref);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (RUNNING_ON_VALGRIND)
|
||||||
|
{
|
||||||
|
private_size += ALIGN_STRUCT (1);
|
||||||
|
allocated -= ALIGN_STRUCT (1);
|
||||||
|
|
||||||
|
*(gpointer *) (allocated + private_size + alloc_size) = NULL;
|
||||||
|
g_free (allocated);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_free (allocated);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
g_ref_pointer_alloc_internal (gsize alloc_size,
|
||||||
|
gboolean clear,
|
||||||
|
GDestroyNotify notify)
|
||||||
|
{
|
||||||
|
gsize private_size = G_REF_PTR_SIZE;
|
||||||
|
gchar *allocated;
|
||||||
|
GRefPtr *real;
|
||||||
|
|
||||||
|
g_return_val_if_fail (alloc_size != 0, NULL);
|
||||||
|
|
||||||
|
if (RUNNING_ON_VALGRIND)
|
||||||
|
{
|
||||||
|
private_size += ALIGN_STRUCT (1);
|
||||||
|
|
||||||
|
if (clear)
|
||||||
|
allocated = g_malloc0 (private_size + alloc_size + sizeof (gpointer));
|
||||||
|
else
|
||||||
|
allocated = g_malloc (private_size + alloc_size + sizeof (gpointer));
|
||||||
|
|
||||||
|
*(gpointer *) (allocated + private_size + alloc_size) = allocated + ALIGN_STRUCT (1);
|
||||||
|
|
||||||
|
VALGRIND_MALLOCLIKE_BLOCK (allocated + private_size, alloc_size + sizeof (gpointer), 0, TRUE);
|
||||||
|
VALGRIND_MALLOCLIKE_BLOCK (allocated + ALIGN_STRUCT (1), private_size - ALIGN_STRUCT (1), 0, TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (clear)
|
||||||
|
allocated = g_malloc0 (private_size + alloc_size);
|
||||||
|
else
|
||||||
|
allocated = g_malloc (private_size + alloc_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef G_ENABLE_DEBUG
|
||||||
|
g_ref_pointer_register (allocated + private_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
real = (GRefPtr *) allocated;
|
||||||
|
real->notify = notify;
|
||||||
|
real->alloc_size = alloc_size;
|
||||||
|
g_ref_count_init (&real->ref_count, FALSE);
|
||||||
|
|
||||||
|
return allocated + private_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_ref_pointer_alloc:
|
||||||
|
* @alloc_size: the number of bytes to allocate
|
||||||
|
* @notify: (nullable): a function to be called when the reference
|
||||||
|
* count drops to zero
|
||||||
|
*
|
||||||
|
* Allocates a reference counted memory area.
|
||||||
|
*
|
||||||
|
* Reference counted memory areas are automatically freed when their
|
||||||
|
* reference count drops to zero.
|
||||||
|
*
|
||||||
|
* Use g_ref_pointer_acquire() to acquire a reference, and
|
||||||
|
* g_ref_pointer_release() to release it when you're done.
|
||||||
|
*
|
||||||
|
* The contents of the returned memory are undefined.
|
||||||
|
*
|
||||||
|
* Returns: a pointer to the allocated memory
|
||||||
|
*
|
||||||
|
* Since: 2.44
|
||||||
|
*/
|
||||||
|
gpointer
|
||||||
|
g_ref_pointer_alloc (gsize alloc_size,
|
||||||
|
GDestroyNotify notify)
|
||||||
|
{
|
||||||
|
return g_ref_pointer_alloc_internal (alloc_size, FALSE, notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_ref_pointer_alloc0:
|
||||||
|
* @alloc_size: the number of bytes to allocate
|
||||||
|
* @notify: (nullable): a function to be called when the reference
|
||||||
|
* count drops to zero
|
||||||
|
*
|
||||||
|
* Allocates a reference counted memory area.
|
||||||
|
*
|
||||||
|
* Reference counted memory areas are automatically freed when their
|
||||||
|
* reference count drops to zero.
|
||||||
|
*
|
||||||
|
* Use g_ref_pointer_acquire() to acquire a reference, and
|
||||||
|
* g_ref_pointer_release() to release it.
|
||||||
|
*
|
||||||
|
* The contents of the returned memory are set to 0.
|
||||||
|
*
|
||||||
|
* Returns: a pointer to the allocated memory
|
||||||
|
*
|
||||||
|
* Since: 2.44
|
||||||
|
*/
|
||||||
|
gpointer
|
||||||
|
g_ref_pointer_alloc0 (gsize alloc_size,
|
||||||
|
GDestroyNotify notify)
|
||||||
|
{
|
||||||
|
return g_ref_pointer_alloc_internal (alloc_size, TRUE, notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_ref_pointer_take:
|
||||||
|
* @data: data to duplicate
|
||||||
|
* @alloc_size: the size of @data
|
||||||
|
* @notify: notification function to be called when the reference
|
||||||
|
* count drops to zero
|
||||||
|
*
|
||||||
|
* Duplicates existing data into a reference counted memory area.
|
||||||
|
*
|
||||||
|
* Returns: the newly allocated reference counted area
|
||||||
|
*
|
||||||
|
* Since: 2.44
|
||||||
|
*/
|
||||||
|
gpointer
|
||||||
|
g_ref_pointer_take (gconstpointer data,
|
||||||
|
gsize alloc_size,
|
||||||
|
GDestroyNotify notify)
|
||||||
|
{
|
||||||
|
gpointer res = g_ref_pointer_alloc (alloc_size, notify);
|
||||||
|
|
||||||
|
memcpy (res, data, alloc_size);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_ref_pointer_acquire:
|
||||||
|
* @ref: a reference counted memory area
|
||||||
|
*
|
||||||
|
* Acquires a reference on the given memory area.
|
||||||
|
*
|
||||||
|
* Use g_ref_pointer_release() to release the reference when done.
|
||||||
|
*
|
||||||
|
* You should only call this function if you are implementing
|
||||||
|
* a reference counted type.
|
||||||
|
*
|
||||||
|
* Returns: the memory area, with its reference count increased by 1
|
||||||
|
*
|
||||||
|
* Since: 2.44
|
||||||
|
*/
|
||||||
|
gpointer
|
||||||
|
g_ref_pointer_acquire (gpointer ref)
|
||||||
|
{
|
||||||
|
GRefPtr *real = G_REF_PTR (ref);
|
||||||
|
|
||||||
|
g_return_val_if_fail (ref != NULL, NULL);
|
||||||
|
#ifdef G_ENABLE_DEBUG
|
||||||
|
g_return_val_if_fail (g_is_ref_pointer (ref), ref);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
g_ref_count_inc (&real->ref_count);
|
||||||
|
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_ref_pointer_release:
|
||||||
|
* @ref: a reference counted memory area
|
||||||
|
*
|
||||||
|
* Releases a reference acquired using g_ref_pointer_acquire().
|
||||||
|
*
|
||||||
|
* If the reference count drops to zero, the notification function
|
||||||
|
* used when allocating the memory will be called, and then the memory
|
||||||
|
* area will be freed.
|
||||||
|
*
|
||||||
|
* You should only call this function if you are implementing
|
||||||
|
* a reference counted type.
|
||||||
|
*
|
||||||
|
* Since: 2.44
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_ref_pointer_release (gpointer ref)
|
||||||
|
{
|
||||||
|
GRefPtr *real = G_REF_PTR (ref);
|
||||||
|
|
||||||
|
g_return_if_fail (ref != NULL);
|
||||||
|
#ifdef G_ENABLE_DEBUG
|
||||||
|
g_return_if_fail (g_is_ref_pointer (ref));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (g_ref_count_dec (&real->ref_count))
|
||||||
|
g_ref_pointer_destroy (ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_ref_pointer_make_atomic:
|
||||||
|
* @ref: a reference counted memory area
|
||||||
|
*
|
||||||
|
* Makes reference count operations on a reference counted memory area
|
||||||
|
* always atomic.
|
||||||
|
*
|
||||||
|
* Since: 2.44
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_ref_pointer_make_atomic (gpointer ref)
|
||||||
|
{
|
||||||
|
GRefPtr *real = G_REF_PTR (ref);
|
||||||
|
|
||||||
|
g_return_if_fail (ref != NULL);
|
||||||
|
#ifdef G_ENABLE_DEBUG
|
||||||
|
g_return_if_fail (g_is_ref_pointer (ref));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
g_ref_count_make_atomic (&real->ref_count);
|
||||||
|
}
|
65
glib/gref.h
Normal file
65
glib/gref.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/* gref.h: Reference counted memory areas
|
||||||
|
*
|
||||||
|
* Copyright 2015 Emmanuele Bassi
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __G_REF_H__
|
||||||
|
#define __G_REF_H__
|
||||||
|
|
||||||
|
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||||
|
#error "Only <glib.h> can be included directly."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glib/gtypes.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
gpointer g_ref_pointer_alloc (gsize alloc_size,
|
||||||
|
GDestroyNotify notify) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE (1);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
gpointer g_ref_pointer_alloc0 (gsize alloc_size,
|
||||||
|
GDestroyNotify notify) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE (1);
|
||||||
|
|
||||||
|
#define g_ref_pointer_new(Type,free_func) ((Type *) g_ref_pointer_alloc (sizeof (Type), (GDestroyNotify) free_func))
|
||||||
|
|
||||||
|
#define g_ref_pointer_new0(Type,free_func) ((Type *) g_ref_pointer_alloc0 (sizeof (Type), (GDestroyNotify) free_func))
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
gpointer g_ref_pointer_take (gconstpointer data,
|
||||||
|
gsize alloc_size,
|
||||||
|
GDestroyNotify notify) G_GNUC_WARN_UNUSED_RESULT;
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
void g_ref_pointer_make_atomic (gpointer ref);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
gpointer g_ref_pointer_acquire (gpointer ref);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
void g_ref_pointer_release (gpointer ref);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
void g_ref_count_init (volatile int *refcount,
|
||||||
|
gboolean atomic);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
void g_ref_count_inc (volatile int *refcount);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
gboolean g_ref_count_dec (volatile int *refcount);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
void g_ref_count_make_atomic (volatile int *refcount);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __G_REF_H__ */
|
Reference in New Issue
Block a user