mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-09-27 17:52:58 +02:00
gobject: Add g_set_object() convenience function to set GObject pointers
Along the same lines as g_clear_object(), g_set_object() is a convenience function to update a GObject pointer, handling reference counting transparently and correctly. Specifically, it handles the case where a pointer is set to its current value. If handled naïvely, that could result in the object instance being finalised. In the following code, that happens when (my_obj == new_value) and the object has a single reference: g_clear_object (&my_obj); my_obj = g_object_ref (new_value); It also simplifies boilerplate code such as set_property() implementations, which are otherwise long and boring. Test cases included. https://bugzilla.gnome.org/show_bug.cgi?id=741589
This commit is contained in:
@@ -651,6 +651,69 @@ GLIB_AVAILABLE_IN_ALL
|
||||
void g_clear_object (volatile GObject **object_ptr);
|
||||
#define g_clear_object(object_ptr) g_clear_pointer ((object_ptr), g_object_unref)
|
||||
|
||||
/**
|
||||
* g_set_object: (skip)
|
||||
* @object_ptr: a pointer to a #GObject reference
|
||||
* @new_object: (nullable) (transfer none): a pointer to the new #GObject to
|
||||
* assign to it, or %NULL to clear the pointer
|
||||
*
|
||||
* Updates a #GObject pointer to refer to @new_object. It increments the
|
||||
* reference count of @new_object (if non-%NULL), decrements the reference
|
||||
* count of the current value of @object_ptr (if non-%NULL), and assigns
|
||||
* @new_object to @object_ptr. The assignment is not atomic.
|
||||
*
|
||||
* @object_ptr must not be %NULL.
|
||||
*
|
||||
* A macro is also included that allows this function to be used without
|
||||
* pointer casts. The function itself is static inline, so its address may vary
|
||||
* between compilation units.
|
||||
*
|
||||
* One convenient usage of this function is in implementing property setters:
|
||||
* |[
|
||||
* void
|
||||
* foo_set_bar (Foo *foo,
|
||||
* Bar *new_bar)
|
||||
* {
|
||||
* g_return_if_fail (IS_FOO (foo));
|
||||
* g_return_if_fail (new_bar == NULL || IS_BAR (new_bar));
|
||||
*
|
||||
* if (g_set_object (&foo->bar, new_bar))
|
||||
* g_object_notify (foo, "bar");
|
||||
* }
|
||||
* ]|
|
||||
*
|
||||
* Returns: %TRUE if the value of @object_ptr changed, %FALSE otherwise
|
||||
*
|
||||
* Since: 2.44
|
||||
*/
|
||||
static inline gboolean
|
||||
(g_set_object) (GObject **object_ptr,
|
||||
GObject *new_object)
|
||||
{
|
||||
/* rely on g_object_[un]ref() to check the pointers are actually GObjects;
|
||||
* elide a (object_ptr != NULL) check because most of the time we will be
|
||||
* operating on struct members with a constant offset, so a NULL check would
|
||||
* not catch bugs */
|
||||
|
||||
if (*object_ptr == new_object)
|
||||
return FALSE;
|
||||
|
||||
if (new_object != NULL)
|
||||
g_object_ref (new_object);
|
||||
if (*object_ptr != NULL)
|
||||
g_object_unref (*object_ptr);
|
||||
|
||||
*object_ptr = new_object;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define g_set_object(object_ptr, new_object) \
|
||||
(/* Check types match. */ \
|
||||
0 ? *(object_ptr) = (new_object), FALSE : \
|
||||
(g_set_object) ((GObject **) (object_ptr), (GObject *) (new_object)) \
|
||||
)
|
||||
|
||||
typedef struct {
|
||||
/*<private>*/
|
||||
union { gpointer p; } priv;
|
||||
|
Reference in New Issue
Block a user