+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
bool in_queue:1; /* In bus->track_queue? */
bool modified:1;
bool recursive:1;
+ sd_bus_destroy_t destroy_callback;
LIST_FIELDS(sd_bus_track, tracks);
};
-#define MATCH_PREFIX \
- "type='signal'," \
- "sender='org.freedesktop.DBus'," \
- "path='/org/freedesktop/DBus'," \
- "interface='org.freedesktop.DBus'," \
- "member='NameOwnerChanged'," \
- "arg0='"
-
-#define MATCH_SUFFIX \
- "'"
-
-#define MATCH_FOR_NAME(name) \
- ({ \
- char *_x; \
- size_t _l = strlen(name); \
- _x = alloca(strlen(MATCH_PREFIX)+_l+strlen(MATCH_SUFFIX)+1); \
- strcpy(stpcpy(stpcpy(_x, MATCH_PREFIX), name), MATCH_SUFFIX); \
- _x; \
- })
+#define MATCH_FOR_NAME(name) \
+ strjoina("type='signal'," \
+ "sender='org.freedesktop.DBus'," \
+ "path='/org/freedesktop/DBus'," \
+ "interface='org.freedesktop.DBus'," \
+ "member='NameOwnerChanged'," \
+ "arg0='", name, "'")
static struct track_item* track_item_free(struct track_item *i) {
sd_bus_track *t;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(track, -EINVAL);
if (!bus->bus_client)
}
_public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
- struct track_item *i;
-
if (!track)
return NULL;
assert(track->n_ref > 0);
+ track->n_ref--;
- if (track->n_ref > 1) {
- track->n_ref--;
+ if (track->n_ref > 0)
return NULL;
- }
-
- while ((i = hashmap_steal_first(track->names)))
- track_item_free(i);
if (track->in_list)
LIST_REMOVE(tracks, track->bus->tracks, track);
bus_track_remove_from_queue(track);
- hashmap_free(track->names);
- sd_bus_unref(track->bus);
+ track->names = hashmap_free_with_destructor(track->names, track_item_free);
+ track->bus = sd_bus_unref(track->bus);
+
+ if (track->destroy_callback)
+ track->destroy_callback(track->userdata);
+
return mfree(track);
}
bus_track_remove_from_queue(track); /* don't dispatch this while we work in it */
- track->n_adding++; /* make sure we aren't dispatched while we synchronously add this match */
- r = sd_bus_add_match(track->bus, &n->slot, match, on_name_owner_changed, track);
- track->n_adding--;
+ r = sd_bus_add_match_async(track->bus, &n->slot, match, on_name_owner_changed, NULL, track);
if (r < 0) {
bus_track_add_to_queue(track);
return r;
}
void bus_track_close(sd_bus_track *track) {
- struct track_item *i;
-
assert(track);
/* Called whenever our bus connected is closed. If so, and our track object is non-empty, dispatch it
return;
/* Let's flush out all names */
- while ((i = hashmap_steal_first(track->names)))
- track_item_free(i);
+ hashmap_clear_with_destructor(track->names, track_item_free);
/* Invoke handler */
if (track->handler)
return ret;
}
-#if 0 /// UNNEEDED by elogind
+_public_ int sd_bus_track_set_destroy_callback(sd_bus_track *track, sd_bus_destroy_t callback) {
+ assert_return(track, -EINVAL);
+
+ track->destroy_callback = callback;
+ return 0;
+}
+
+_public_ int sd_bus_track_get_destroy_callback(sd_bus_track *track, sd_bus_destroy_t *ret) {
+ assert_return(track, -EINVAL);
+
+ if (ret)
+ *ret = track->destroy_callback;
+
+ return !!track->destroy_callback;
+}
+
_public_ int sd_bus_track_set_recursive(sd_bus_track *track, int b) {
assert_return(track, -EINVAL);
return i->n_ref;
}
-#endif // 0