mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-29 04:14:11 +02:00
Add g_clear_pointer()
Also reimplement g_clear_object() using g_clear_pointer() https://bugzilla.gnome.org/show_bug.cgi?id=674634
This commit is contained in:
@@ -682,6 +682,7 @@ g_markup_printf_escaped
|
||||
g_markup_vprintf_escaped
|
||||
g_markup_collect_attributes
|
||||
g_free
|
||||
g_clear_pointer
|
||||
g_malloc
|
||||
g_malloc0
|
||||
g_malloc_n
|
||||
|
39
glib/gmem.c
39
glib/gmem.c
@@ -253,6 +253,45 @@ g_free (gpointer mem)
|
||||
TRACE(GLIB_MEM_FREE((void*) mem));
|
||||
}
|
||||
|
||||
/**
|
||||
* g_clear_pointer: (skip)
|
||||
* @pp: a pointer to a variable, struct member etc. holding a pointer
|
||||
* @destroy: a function to which a gpointer can be passed, to destroy *@pp
|
||||
*
|
||||
* Clears a reference to a variable.
|
||||
*
|
||||
* @pp must not be %NULL.
|
||||
*
|
||||
* If the reference is %NULL then this function does nothing.
|
||||
* Otherwise, the variable is destroyed using @destroy and the
|
||||
* pointer is set to %NULL.
|
||||
*
|
||||
* This function is threadsafe and modifies the pointer atomically,
|
||||
* using memory barriers where needed.
|
||||
*
|
||||
* A macro is also included that allows this function to be used without
|
||||
* pointer casts.
|
||||
*
|
||||
* Since: 2.34
|
||||
**/
|
||||
#undef g_clear_pointer
|
||||
void
|
||||
g_clear_pointer (gpointer *pp,
|
||||
GDestroyNotify destroy)
|
||||
{
|
||||
gpointer _p;
|
||||
|
||||
/* This is a little frustrating.
|
||||
* Would be nice to have an atomic exchange (with no compare).
|
||||
*/
|
||||
do
|
||||
_p = g_atomic_pointer_get (pp);
|
||||
while G_UNLIKELY (!g_atomic_pointer_compare_and_exchange (pp, _p, NULL));
|
||||
|
||||
if (_p)
|
||||
destroy (_p);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_try_malloc:
|
||||
* @n_bytes: number of bytes to allocate.
|
||||
|
18
glib/gmem.h
18
glib/gmem.h
@@ -69,6 +69,10 @@ typedef struct _GMemVTable GMemVTable;
|
||||
|
||||
void g_free (gpointer mem);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_34
|
||||
void g_clear_pointer (gpointer *pp,
|
||||
GDestroyNotify destroy);
|
||||
|
||||
gpointer g_malloc (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
||||
gpointer g_malloc0 (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
||||
gpointer g_realloc (gpointer mem,
|
||||
@@ -93,6 +97,20 @@ gpointer g_try_realloc_n (gpointer mem,
|
||||
gsize n_blocks,
|
||||
gsize n_block_bytes) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
#define g_clear_pointer(pp, destroy) \
|
||||
G_STMT_START { \
|
||||
G_STATIC_ASSERT (sizeof (*(pp)) == sizeof (gpointer)); \
|
||||
/* Only one access, please */ \
|
||||
gpointer *_pp = (gpointer *) pp; \
|
||||
gpointer _p; \
|
||||
\
|
||||
do \
|
||||
_p = g_atomic_pointer_get (_pp); \
|
||||
while G_UNLIKELY (!g_atomic_pointer_compare_and_exchange (_pp, _p, NULL)); \
|
||||
\
|
||||
if (_p) \
|
||||
((GDestroyNotify) (destroy)) (_p); \
|
||||
} G_STMT_END
|
||||
|
||||
/* Optimise: avoid the call to the (slower) _n function if we can
|
||||
* determine at compile-time that no overflow happens.
|
||||
|
Reference in New Issue
Block a user