obj->type = type;
INIT_LIST_HEAD(&obj->list);
INIT_LIST_HEAD(&obj->events);
+ INIT_LIST_HEAD(&obj->subscribers);
+ INIT_LIST_HEAD(&obj->target_list);
if (type)
type->refcount++;
return NULL;
}
+void ubus_subscribe(struct ubus_object *obj, struct ubus_object *target)
+{
+ struct ubus_subscription *s;
+ bool first = list_empty(&target->subscribers);
+
+ s = calloc(1, sizeof(*s));
+ if (!s)
+ return;
+
+ s->subscriber = obj;
+ s->target = target;
+ list_add(&s->list, &target->subscribers);
+ list_add(&s->target_list, &obj->target_list);
+
+ if (first)
+ ubus_notify_subscription(target);
+}
+
+void ubus_unsubscribe(struct ubus_subscription *s)
+{
+ struct ubus_object *obj = s->target;
+
+ list_del(&s->list);
+ list_del(&s->target_list);
+ free(s);
+
+ if (list_empty(&obj->subscribers))
+ ubus_notify_subscription(obj);
+}
+
void ubusd_free_object(struct ubus_object *obj)
{
+ struct ubus_subscription *s, *tmp;
+
+ list_for_each_entry_safe(s, tmp, &obj->target_list, target_list) {
+ ubus_unsubscribe(s);
+ }
+ list_for_each_entry_safe(s, tmp, &obj->subscribers, list) {
+ ubus_notify_unsubscribe(s);
+ }
+
ubusd_event_cleanup_object(obj);
if (obj->path.key) {
ubusd_send_obj_event(obj, false);