Graph: pass remove listeners when adding listeners
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Fri, 21 Jul 2017 20:34:29 +0000 (16:34 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 11 Aug 2017 22:54:15 +0000 (18:54 -0400)
With this patch, when you call bt_graph_add_*_listener(), you can also
provide a "remove listener" which is called when the added listener is
removed when the graph object is destroyed. This is useful when you
dynamically allocate data only for the listener to add and you are not
the only owner of the graph object: the remove listener is where to
free/release this data.

Existing CLIs and tests are modified to match this change.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
cli/babeltrace.c
include/babeltrace/graph/graph-internal.h
include/babeltrace/graph/graph.h
lib/graph/graph.c
tests/lib/test_graph_topo.c
tests/plugins/test-utils-muxer.c

index 6920aabc6e697a2c07e03071ac4971e658afea60..215092fd0ceb58e0760bd9c3285de3171ee21144 100644 (file)
@@ -1840,28 +1840,28 @@ int cmd_run_ctx_init(struct cmd_run_ctx *ctx, struct bt_config *cfg)
 
        the_graph = ctx->graph;
        ret = bt_graph_add_port_added_listener(ctx->graph,
-               graph_port_added_listener, ctx);
+               graph_port_added_listener, NULL, ctx);
        if (ret < 0) {
                BT_LOGE_STR("Cannot add \"port added\" listener to graph.");
                goto error;
        }
 
        ret = bt_graph_add_port_removed_listener(ctx->graph,
-               graph_port_removed_listener, ctx);
+               graph_port_removed_listener, NULL, ctx);
        if (ret < 0) {
                BT_LOGE_STR("Cannot add \"port removed\" listener to graph.");
                goto error;
        }
 
        ret = bt_graph_add_ports_connected_listener(ctx->graph,
-               graph_ports_connected_listener, ctx);
+               graph_ports_connected_listener, NULL, ctx);
        if (ret < 0) {
                BT_LOGE_STR("Cannot add \"ports connected\" listener to graph.");
                goto error;
        }
 
        ret = bt_graph_add_ports_disconnected_listener(ctx->graph,
-               graph_ports_disconnected_listener, ctx);
+               graph_ports_disconnected_listener, NULL, ctx);
        if (ret < 0) {
                BT_LOGE_STR("Cannot add \"ports disconnected\" listener to graph.");
                goto error;
index d418642595c0bbf7dbd847a81d316d118d29394b..1e8b1b79ab3407671b39848e4b1d4baa89f119be 100644 (file)
@@ -58,6 +58,7 @@ struct bt_graph {
        GQueue *sinks_to_consume;
 
        bt_bool canceled;
+       bt_bool in_remove_listener;
 
        struct {
                GArray *port_added;
index a5077c4901991bcc9e343f6aaf4f3a048d375fb3..f790e4496813c2a884d0605fdefb9b12c95142cc 100644 (file)
@@ -66,6 +66,7 @@ typedef void (*bt_graph_ports_disconnected_listener)(
                struct bt_component *downstream_component,
                struct bt_port *upstream_port, struct bt_port *downstream_port,
                void *data);
+typedef void (* bt_graph_listener_removed)(void *data);
 
 extern struct bt_graph *bt_graph_create(void);
 
@@ -106,16 +107,20 @@ extern enum bt_graph_status bt_graph_run(struct bt_graph *graph);
 extern enum bt_graph_status bt_graph_consume(struct bt_graph *graph);
 
 extern int bt_graph_add_port_added_listener(struct bt_graph *graph,
-               bt_graph_port_added_listener listener, void *data);
+               bt_graph_port_added_listener listener,
+               bt_graph_listener_removed listener_removed, void *data);
 
 extern int bt_graph_add_port_removed_listener(struct bt_graph *graph,
-               bt_graph_port_removed_listener listener, void *data);
+               bt_graph_port_removed_listener listener,
+               bt_graph_listener_removed listener_removed, void *data);
 
 extern int bt_graph_add_ports_connected_listener(struct bt_graph *graph,
-               bt_graph_ports_connected_listener listener, void *data);
+               bt_graph_ports_connected_listener listener,
+               bt_graph_listener_removed listener_removed, void *data);
 
 extern int bt_graph_add_ports_disconnected_listener(struct bt_graph *graph,
-               bt_graph_ports_disconnected_listener listener, void *data);
+               bt_graph_ports_disconnected_listener listener,
+               bt_graph_listener_removed listener_removed, void *data);
 
 extern enum bt_graph_status bt_graph_cancel(struct bt_graph *graph);
 extern bt_bool bt_graph_is_canceled(struct bt_graph *graph);
index e7f8db3f3e76f3b5c3e0f9b18a724a06ba6b00cd..747a282601d5622543139a683b15e62572db9515 100644 (file)
 
 struct bt_graph_listener {
        void *func;
+       bt_graph_listener_removed removed;
        void *data;
 };
 
+static
+int init_listeners_array(GArray **listeners)
+{
+       int ret = 0;
+
+       assert(listeners);
+       *listeners = g_array_new(FALSE, TRUE, sizeof(struct bt_graph_listener));
+       if (!*listeners) {
+               BT_LOGE_STR("Failed to allocate one GArray.");
+               ret = -1;
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+static
+void call_remove_listeners(GArray *listeners)
+{
+       size_t i;
+
+       for (i = 0; i < listeners->len; i++) {
+               struct bt_graph_listener listener =
+                       g_array_index(listeners, struct bt_graph_listener, i);
+
+               if (listener.removed) {
+                       listener.removed(listener.data);
+               }
+       }
+}
+
 static
 void bt_graph_destroy(struct bt_object *obj)
 {
@@ -88,6 +121,12 @@ void bt_graph_destroy(struct bt_object *obj)
         */
        (void) bt_graph_cancel(graph);
 
+       /* Call all remove listeners */
+       call_remove_listeners(graph->listeners.port_added);
+       call_remove_listeners(graph->listeners.port_removed);
+       call_remove_listeners(graph->listeners.ports_connected);
+       call_remove_listeners(graph->listeners.ports_disconnected);
+
        if (graph->connections) {
                BT_LOGD_STR("Destroying connections.");
                g_ptr_array_free(graph->connections, TRUE);
@@ -119,23 +158,6 @@ void bt_graph_destroy(struct bt_object *obj)
        g_free(graph);
 }
 
-static
-int init_listeners_array(GArray **listeners)
-{
-       int ret = 0;
-
-       assert(listeners);
-       *listeners = g_array_new(FALSE, TRUE, sizeof(struct bt_graph_listener));
-       if (!*listeners) {
-               BT_LOGE_STR("Failed to allocate one GArray.");
-               ret = -1;
-               goto end;
-       }
-
-end:
-       return ret;
-}
-
 struct bt_graph *bt_graph_create(void)
 {
        struct bt_graph *graph;
@@ -530,10 +552,11 @@ end:
 }
 
 static
-int add_listener(GArray *listeners, void *func, void *data)
+int add_listener(GArray *listeners, void *func, void *removed, void *data)
 {
        struct bt_graph_listener listener = {
                .func = func,
+               .removed = removed,
                .data = data,
        };
 
@@ -543,7 +566,8 @@ int add_listener(GArray *listeners, void *func, void *data)
 
 int bt_graph_add_port_added_listener(
                struct bt_graph *graph,
-               bt_graph_port_added_listener listener, void *data)
+               bt_graph_port_added_listener listener,
+               bt_graph_listener_removed listener_removed, void *data)
 {
        int ret;
 
@@ -553,13 +577,21 @@ int bt_graph_add_port_added_listener(
                goto end;
        }
 
+       if (graph->in_remove_listener) {
+               BT_LOGW("Cannot call this function during the execution of a remove listener: "
+                       "addr=%p", graph);
+               ret = -1;
+               goto end;
+       }
+
        if (!listener) {
                BT_LOGW_STR("Invalid parameter: listener is NULL.");
                ret = -1;
                goto end;
        }
 
-       ret = add_listener(graph->listeners.port_added, listener, data);
+       ret = add_listener(graph->listeners.port_added, listener,
+               listener_removed, data);
        BT_LOGV("Added \"port added\" listener to graph: "
                "graph-addr=%p, listener-addr=%p, pos=%d",
                graph, listener, ret);
@@ -570,7 +602,8 @@ end:
 
 int bt_graph_add_port_removed_listener(
                struct bt_graph *graph,
-               bt_graph_port_removed_listener listener, void *data)
+               bt_graph_port_removed_listener listener,
+               bt_graph_listener_removed listener_removed, void *data)
 {
        int ret;
 
@@ -580,13 +613,21 @@ int bt_graph_add_port_removed_listener(
                goto end;
        }
 
+       if (graph->in_remove_listener) {
+               BT_LOGW("Cannot call this function during the execution of a remove listener: "
+                       "addr=%p", graph);
+               ret = -1;
+               goto end;
+       }
+
        if (!listener) {
                BT_LOGW_STR("Invalid parameter: listener is NULL.");
                ret = -1;
                goto end;
        }
 
-       ret = add_listener(graph->listeners.port_removed, listener, data);
+       ret = add_listener(graph->listeners.port_removed, listener,
+               listener_removed, data);
        BT_LOGV("Added \"port removed\" listener to graph: "
                "graph-addr=%p, listener-addr=%p, pos=%d",
                graph, listener, ret);
@@ -597,7 +638,8 @@ end:
 
 int bt_graph_add_ports_connected_listener(
                struct bt_graph *graph,
-               bt_graph_ports_connected_listener listener, void *data)
+               bt_graph_ports_connected_listener listener,
+               bt_graph_listener_removed listener_removed, void *data)
 {
        int ret;
 
@@ -607,13 +649,21 @@ int bt_graph_add_ports_connected_listener(
                goto end;
        }
 
+       if (graph->in_remove_listener) {
+               BT_LOGW("Cannot call this function during the execution of a remove listener: "
+                       "addr=%p", graph);
+               ret = -1;
+               goto end;
+       }
+
        if (!listener) {
                BT_LOGW_STR("Invalid parameter: listener is NULL.");
                ret = -1;
                goto end;
        }
 
-       ret = add_listener(graph->listeners.ports_connected, listener, data);
+       ret = add_listener(graph->listeners.ports_connected, listener,
+               listener_removed, data);
        BT_LOGV("Added \"port connected\" listener to graph: "
                "graph-addr=%p, listener-addr=%p, pos=%d",
                graph, listener, ret);
@@ -624,7 +674,8 @@ end:
 
 int bt_graph_add_ports_disconnected_listener(
                struct bt_graph *graph,
-               bt_graph_ports_disconnected_listener listener, void *data)
+               bt_graph_ports_disconnected_listener listener,
+               bt_graph_listener_removed listener_removed, void *data)
 {
        int ret;
 
@@ -634,13 +685,21 @@ int bt_graph_add_ports_disconnected_listener(
                goto end;
        }
 
+       if (graph->in_remove_listener) {
+               BT_LOGW("Cannot call this function during the execution of a remove listener: "
+                       "addr=%p", graph);
+               ret = -1;
+               goto end;
+       }
+
        if (!listener) {
                BT_LOGW_STR("Invalid parameter: listener is NULL.");
                ret = -1;
                goto end;
        }
 
-       ret = add_listener(graph->listeners.ports_disconnected, listener, data);
+       ret = add_listener(graph->listeners.ports_disconnected, listener,
+               listener_removed, data);
        BT_LOGV("Added \"port disconnected\" listener to graph: "
                "graph-addr=%p, listener-addr=%p, pos=%d",
                graph, listener, ret);
index 038ce3eba6f8230467d43325efb130d972f65965..4066587e27b47d98ad01a9a0a8104fa496150a86 100644 (file)
@@ -618,16 +618,17 @@ struct bt_graph *create_graph(void)
        int ret;
 
        assert(graph);
-       ret = bt_graph_add_port_added_listener(graph, graph_port_added, NULL);
+       ret = bt_graph_add_port_added_listener(graph, graph_port_added, NULL,
+               NULL);
        assert(ret >= 0);
        ret = bt_graph_add_port_removed_listener(graph, graph_port_removed,
-               NULL);
+               NULL, NULL);
        assert(ret >= 0);
-       ret = bt_graph_add_ports_connected_listener(graph, graph_ports_connected,
-               NULL);
+       ret = bt_graph_add_ports_connected_listener(graph,
+               graph_ports_connected, NULL, NULL);
        assert(ret >= 0);
        ret = bt_graph_add_ports_disconnected_listener(graph,
-               graph_ports_disconnected, NULL);
+               graph_ports_disconnected, NULL, NULL);
        assert(ret >= 0);
        return graph;
 }
index df507074f56975a3d269c48e8e1cc0c33accd55e..85ed44a92cfef868612e7b4e91e73184a647b603 100644 (file)
@@ -1464,7 +1464,7 @@ void test_single_end_then_multiple_full(void)
        graph_listener_data.muxer = muxer_comp;
        graph_listener_data.sink = sink_comp;
        ret = bt_graph_add_port_added_listener(graph,
-               graph_port_added_listener_connect_to_avail_muxer_port,
+               graph_port_added_listener_connect_to_avail_muxer_port, NULL,
                &graph_listener_data);
        assert(ret >= 0);
 
@@ -1592,7 +1592,7 @@ void test_single_again_end_then_multiple_full(void)
        graph_listener_data.muxer = muxer_comp;
        graph_listener_data.sink = sink_comp;
        ret = bt_graph_add_port_added_listener(graph,
-               graph_port_added_listener_connect_to_avail_muxer_port,
+               graph_port_added_listener_connect_to_avail_muxer_port, NULL,
                &graph_listener_data);
        assert(ret >= 0);
 
This page took 0.030642 seconds and 4 git commands to generate.