summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-09-06 15:32:52 +0200
committerThomas Haller <thaller@redhat.com>2017-09-08 11:05:04 +0200
commit959944d6230e4a9e3983f4c24bb4454790d62ebf (patch)
tree41d547a55314e2c924853673dba078453c5735e8
parent19716df23ddfd3047b64620c389fa336e4427c69 (diff)
downloadNetworkManager-959944d6230e4a9e3983f4c24bb4454790d62ebf.tar.gz
shared: add nm_g_object_ref_set() and nm_clear_g_object()
- nm_clear_g_object() is like g_clear_object() but: - it returns a boolean value, indicating that something was cleared. - it includes an nm_assert() to check that the pointer is still valid. - it uses typeof() instead of blindly casting the argument. - nm_g_object_ref_set() combines nm_clear_g_object() and resetting the pointer to a new object, including taking a reference. - also returns a boolean, indicating whether something changed. - it gets the order of operations right: first it increses the ref-count, before unrefing the old object. - like nm_clear_g_object() and nm_clear_g_free() it first sets the destination to NULL, instead of leaving a dangling pointer for the duraction of the unref/free call. - fix nm_clear_g_free() not to use a possibly dangling pointer. Striclty speaking, that is undefined behavior.
-rw-r--r--shared/nm-utils/nm-macros-internal.h55
1 files changed, 52 insertions, 3 deletions
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h
index d11766f915..5564197566 100644
--- a/shared/nm-utils/nm-macros-internal.h
+++ b/shared/nm-utils/nm-macros-internal.h
@@ -619,6 +619,36 @@ nm_g_object_unref (gpointer obj)
g_object_unref (obj);
}
+/* Assigns GObject @obj to destination @pdst, and takes an additional ref.
+ * The previous value of @pdst is unrefed.
+ *
+ * It makes sure to first increase the ref-count of @obj, and handles %NULL
+ * @obj correctly.
+ * */
+#define nm_g_object_ref_set(pp, obj) \
+ ({ \
+ typeof (*(pp)) *const _pp = (pp); \
+ typeof (**_pp) *const _obj = (obj); \
+ typeof (**_pp) *_p; \
+ gboolean _changed = FALSE; \
+ \
+ if ( _pp \
+ && ((_p = *_pp) != _obj)) { \
+ if (_obj) { \
+ nm_assert (G_IS_OBJECT (_obj)); \
+ g_object_ref (_obj); \
+ } \
+ if (_p) { \
+ nm_assert (G_IS_OBJECT (_p)); \
+ *_pp = NULL; \
+ g_object_unref (_p); \
+ } \
+ *_pp = _obj; \
+ _changed = TRUE; \
+ } \
+ _changed; \
+ })
+
/* basically, replaces
* g_clear_pointer (&location, g_free)
* with
@@ -631,13 +661,32 @@ nm_g_object_unref (gpointer obj)
#define nm_clear_g_free(pp) \
({ \
typeof (*(pp)) *_pp = (pp); \
- typeof (**_pp) *_p = *_pp; \
+ typeof (**_pp) *_p; \
+ gboolean _changed = FALSE; \
\
- if (_p) { \
+ if ( _pp \
+ && (_p = *_pp)) { \
*_pp = NULL; \
g_free (_p); \
+ _changed = TRUE; \
+ } \
+ _changed; \
+ })
+
+#define nm_clear_g_object(pp) \
+ ({ \
+ typeof (*(pp)) *_pp = (pp); \
+ typeof (**_pp) *_p; \
+ gboolean _changed = FALSE; \
+ \
+ if ( _pp \
+ && (_p = *_pp)) { \
+ nm_assert (G_IS_OBJECT (_p)); \
+ *_pp = NULL; \
+ g_object_unref (_p); \
+ _changed = TRUE; \
} \
- !!_p; \
+ _changed; \
})
static inline gboolean