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.
This commit is contained in:
Thomas Haller
2018-04-03 16:37:20 +02:00
parent 4127f1234f
commit 86229a669b
2 changed files with 129 additions and 0 deletions

View File

@@ -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);
}

View File

@@ -179,4 +179,34 @@ void nm_dbus_utils_g_value_set_object_path_from_hash (GValue *value,
GHashTable *hash, GHashTable *hash,
gboolean expect_all_exported); 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__ */ #endif /* __NM_DBUS_UTILS_H__ */