summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-04-03 16:37:20 +0200
committerThomas Haller <thaller@redhat.com>2018-04-13 09:09:46 +0200
commit86229a669bc3c51faf19f15c6a382c20f849b78e (patch)
tree395e904ee1d0271cc3690be13ca8dbbc6727700a
parent4127f1234fc4593cb80ad01435ac2b1743c8d5e2 (diff)
downloadNetworkManager-86229a669bc3c51faf19f15c6a382c20f849b78e.tar.gz
core: add NMDBusTrackObjPath helper
When one D-Bus object exposes (the path of) another D-Bus object, we want that the path property gets cleared before the other object gets unexported(). That essentially requires to register to the "exported-changed" signal. Add a helper struct NMDBusTrackObjPath to help with this.
-rw-r--r--src/nm-dbus-utils.c99
-rw-r--r--src/nm-dbus-utils.h30
2 files changed, 129 insertions, 0 deletions
diff --git a/src/nm-dbus-utils.c b/src/nm-dbus-utils.c
index b79cc34371..5a57206c76 100644
--- a/src/nm-dbus-utils.c
+++ b/src/nm-dbus-utils.c
@@ -207,3 +207,102 @@ nm_dbus_utils_get_paths_for_clist (const CList *lst_head,
}
/*****************************************************************************/
+
+void
+nm_dbus_track_obj_path_init (NMDBusTrackObjPath *track,
+ GObject *target,
+ const GParamSpec *pspec)
+{
+ nm_assert (track);
+ nm_assert (G_IS_OBJECT (target));
+ nm_assert (G_IS_PARAM_SPEC (pspec));
+
+ track->_obj = NULL;
+ track->_notify_target = target;
+ track->_notify_pspec = pspec;
+ track->_notify_signal_id = 0;
+ track->_visible = FALSE;
+}
+
+void
+nm_dbus_track_obj_path_deinit (NMDBusTrackObjPath *track)
+{
+ /* we allow deinit() to be called multiple times (e.g. from
+ * dispose(), which must be re-entrant). */
+ nm_assert (track);
+ nm_assert (!track->_notify_target || G_IS_OBJECT (track->_notify_target));
+
+ nm_clear_g_signal_handler (track->obj, &track->_notify_signal_id);
+ track->_notify_target = NULL;
+ track->_notify_pspec = NULL;
+ track->_visible = FALSE;
+ nm_clear_g_object (&track->_obj);
+}
+
+void
+nm_dbus_track_obj_path_notify (const NMDBusTrackObjPath *track)
+{
+ nm_assert (track);
+ nm_assert (G_IS_OBJECT (track->_notify_target));
+ nm_assert (G_IS_PARAM_SPEC (track->_notify_pspec));
+
+ g_object_notify_by_pspec (track->_notify_target,
+ (GParamSpec *) track->_notify_pspec);
+}
+
+const char *
+nm_dbus_track_obj_path_get (const NMDBusTrackObjPath *track)
+{
+ nm_assert (track);
+ nm_assert (G_IS_OBJECT (track->_notify_target));
+
+ return track->obj && track->visible
+ ? nm_dbus_object_get_path_still_exported (track->obj)
+ : NULL;
+}
+
+static void
+_track_obj_exported_changed (NMDBusObject *obj,
+ NMDBusTrackObjPath *track)
+{
+ nm_dbus_track_obj_path_notify (track);
+}
+
+void
+nm_dbus_track_obj_path_set (NMDBusTrackObjPath *track,
+ gpointer obj,
+ gboolean visible)
+{
+ gs_unref_object NMDBusObject *old_obj = NULL;
+ const char *old_path;
+
+ nm_assert (track);
+ nm_assert (G_IS_OBJECT (track->_notify_target));
+
+ g_return_if_fail (!obj || NM_IS_DBUS_OBJECT (obj));
+
+ if ( track->obj == obj
+ && track->visible == !!visible)
+ return;
+
+ old_path = nm_dbus_track_obj_path_get (track);
+
+ track->_visible = visible;
+
+ if (track->obj != obj) {
+ nm_clear_g_signal_handler (track->obj, &track->_notify_signal_id);
+
+ old_obj = track->obj;
+ track->_obj = nm_g_object_ref (obj);
+
+ if (obj) {
+ track->_notify_signal_id = g_signal_connect (obj,
+ NM_DBUS_OBJECT_EXPORTED_CHANGED,
+ G_CALLBACK (_track_obj_exported_changed),
+ track);
+ }
+ }
+
+ if (!nm_streq0 (old_path, nm_dbus_track_obj_path_get (track)))
+ nm_dbus_track_obj_path_notify (track);
+}
diff --git a/src/nm-dbus-utils.h b/src/nm-dbus-utils.h
index 3107a29c82..e7e930e938 100644
--- a/src/nm-dbus-utils.h
+++ b/src/nm-dbus-utils.h
@@ -179,4 +179,34 @@ void nm_dbus_utils_g_value_set_object_path_from_hash (GValue *value,
GHashTable *hash,
gboolean expect_all_exported);
+/*****************************************************************************/
+
+typedef struct {
+ union {
+ gpointer const obj;
+ gpointer _obj;
+ };
+ GObject *_notify_target;
+ const GParamSpec *_notify_pspec;
+ gulong _notify_signal_id;
+ union {
+ const bool visible;
+ bool _visible;
+ };
+} NMDBusTrackObjPath;
+
+void nm_dbus_track_obj_path_init (NMDBusTrackObjPath *track,
+ GObject *target,
+ const GParamSpec *pspec);
+
+void nm_dbus_track_obj_path_deinit (NMDBusTrackObjPath *track);
+
+void nm_dbus_track_obj_path_notify (const NMDBusTrackObjPath *track);
+
+const char *nm_dbus_track_obj_path_get (const NMDBusTrackObjPath *track);
+
+void nm_dbus_track_obj_path_set (NMDBusTrackObjPath *track,
+ gpointer obj,
+ gboolean visible);
+
#endif /* __NM_DBUS_UTILS_H__ */