mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-03 06:32:10 +01: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:
parent
3f816dc5d1
commit
00285b7517
@ -925,6 +925,7 @@ g_try_realloc_n
|
||||
|
||||
<SUBSECTION>
|
||||
g_free
|
||||
g_clear_pointer
|
||||
g_mem_gc_friendly
|
||||
|
||||
<SUBSECTION>
|
||||
|
@ -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.
|
||||
|
@ -3057,18 +3057,7 @@ g_object_unref (gpointer _object)
|
||||
void
|
||||
g_clear_object (volatile GObject **object_ptr)
|
||||
{
|
||||
gpointer *ptr = (gpointer) object_ptr;
|
||||
gpointer old;
|
||||
|
||||
/* This is a little frustrating.
|
||||
* Would be nice to have an atomic exchange (with no compare).
|
||||
*/
|
||||
do
|
||||
old = g_atomic_pointer_get (ptr);
|
||||
while G_UNLIKELY (!g_atomic_pointer_compare_and_exchange (ptr, old, NULL));
|
||||
|
||||
if (old)
|
||||
g_object_unref (old);
|
||||
g_clear_pointer (object_ptr, g_object_unref);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -561,19 +561,7 @@ G_STMT_START { \
|
||||
G_OBJECT_WARN_INVALID_PSPEC ((object), "property", (property_id), (pspec))
|
||||
|
||||
void g_clear_object (volatile GObject **object_ptr);
|
||||
#define g_clear_object(object_ptr) \
|
||||
G_STMT_START { \
|
||||
/* Only one access, please */ \
|
||||
gpointer *_p = (gpointer) (object_ptr); \
|
||||
gpointer _o; \
|
||||
\
|
||||
do \
|
||||
_o = g_atomic_pointer_get (_p); \
|
||||
while G_UNLIKELY (!g_atomic_pointer_compare_and_exchange (_p, _o, NULL));\
|
||||
\
|
||||
if (_o) \
|
||||
g_object_unref (_o); \
|
||||
} G_STMT_END
|
||||
#define g_clear_object(object_ptr) g_clear_pointer ((object_ptr), g_object_unref)
|
||||
|
||||
typedef struct {
|
||||
/*<private>*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user