lib: do not allow port to be removed when message iterators are active
[babeltrace.git] / lib / graph / graph.c
index 3b48c561b685718aab9702040d84b3f2cd15a3c2..f28954188a3659764e3c04a6cc0c626ff57944e9 100644 (file)
@@ -118,11 +118,11 @@ void destroy_graph(struct bt_object *obj)
         * in this situation:
         *
         * 1. We put and destroy a connection.
-        * 2. This connection's destructor finalizes its active
-        *    message iterators.
-        * 3. A message iterator's finalization function gets a
-        *    new reference on its component (reference count goes from
-        *    0 to 1).
+        * 2. This connection's destructor finalizes its active message
+        *    iterators.
+        * 3. A message iterator's finalization function gets a new
+        *    reference on its component (reference count goes from 0 to
+        *    1).
         * 4. Since this component's reference count goes to 1, it takes
         *    a reference on its parent (this graph). This graph's
         *    reference count goes from 0 to 1.
@@ -131,8 +131,8 @@ void destroy_graph(struct bt_object *obj)
         * 6. Since this component's reference count goes from 1 to 0,
         *    it puts its parent (this graph). This graph's reference
         *    count goes from 1 to 0.
-        * 7. Since this graph's reference count goes from 1 to 0,
-        *    its destructor is called (this function).
+        * 7. Since this graph's reference count goes from 1 to 0, its
+        *    destructor is called (this function).
         *
         * With the incrementation below, the graph's reference count at
         * step 4 goes from 1 to 2, and from 2 to 1 at step 6. This
@@ -166,12 +166,16 @@ void destroy_graph(struct bt_object *obj)
                graph->listeners.sink_input_port_removed);
        CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_connected,
                graph->listeners.source_filter_ports_connected);
+       CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_connected,
+               graph->listeners.filter_filter_ports_connected);
        CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_connected,
                graph->listeners.source_sink_ports_connected);
        CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_connected,
                graph->listeners.filter_sink_ports_connected);
        CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_disconnected,
                graph->listeners.source_filter_ports_disconnected);
+       CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_disconnected,
+               graph->listeners.filter_filter_ports_disconnected);
        CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_disconnected,
                graph->listeners.source_sink_ports_disconnected);
        CALL_REMOVE_LISTENERS(struct bt_graph_listener_ports_disconnected,
@@ -245,6 +249,12 @@ void destroy_graph(struct bt_object *obj)
                graph->listeners.source_filter_ports_connected = NULL;
        }
 
+       if (graph->listeners.filter_filter_ports_connected) {
+               g_array_free(graph->listeners.filter_filter_ports_connected,
+                       TRUE);
+               graph->listeners.filter_filter_ports_connected = NULL;
+       }
+
        if (graph->listeners.source_sink_ports_connected) {
                g_array_free(graph->listeners.source_sink_ports_connected,
                        TRUE);
@@ -269,6 +279,12 @@ void destroy_graph(struct bt_object *obj)
                graph->listeners.source_sink_ports_disconnected = NULL;
        }
 
+       if (graph->listeners.filter_filter_ports_disconnected) {
+               g_array_free(graph->listeners.filter_filter_ports_disconnected,
+                       TRUE);
+               graph->listeners.filter_filter_ports_disconnected = NULL;
+       }
+
        if (graph->listeners.filter_sink_ports_disconnected) {
                g_array_free(graph->listeners.filter_sink_ports_disconnected,
                        TRUE);
@@ -420,6 +436,14 @@ struct bt_graph *bt_graph_create(void)
                goto error;
        }
 
+       INIT_LISTENERS_ARRAY(struct bt_graph_listener_ports_connected,
+               graph->listeners.filter_filter_ports_connected);
+
+       if (!graph->listeners.filter_filter_ports_connected) {
+               ret = -1;
+               goto error;
+       }
+
        INIT_LISTENERS_ARRAY(struct bt_graph_listener_ports_connected,
                graph->listeners.filter_sink_ports_connected);
 
@@ -444,6 +468,14 @@ struct bt_graph *bt_graph_create(void)
                goto error;
        }
 
+       INIT_LISTENERS_ARRAY(struct bt_graph_listener_ports_disconnected,
+               graph->listeners.filter_filter_ports_disconnected);
+
+       if (!graph->listeners.filter_filter_ports_disconnected) {
+               ret = -1;
+               goto error;
+       }
+
        INIT_LISTENERS_ARRAY(struct bt_graph_listener_ports_disconnected,
                graph->listeners.filter_sink_ports_disconnected);
 
@@ -608,7 +640,7 @@ enum bt_graph_status bt_graph_connect_ports(
                goto end;
        }
 
-       connection->msgied_upstream_port_connected = true;
+       connection->notified_upstream_port_connected = true;
        BT_LIB_LOGD("Notifying downstream component that its port is connected: "
                "%![comp-]+c, %![port-]+p", downstream_component,
                downstream_port);
@@ -626,14 +658,14 @@ enum bt_graph_status bt_graph_connect_ports(
                goto end;
        }
 
-       connection->msgied_downstream_port_connected = true;
+       connection->notified_downstream_port_connected = true;
 
        /*
         * Notify the graph's creator that both ports are connected.
         */
        BT_LOGD_STR("Notifying graph's user that new component ports are connected.");
        bt_graph_notify_ports_connected(graph, upstream_port, downstream_port);
-       connection->msgied_graph_ports_connected = true;
+       connection->notified_graph_ports_connected = true;
        BT_LIB_LOGD("Connected component ports within graph: "
                "%![graph-]+g, %![up-comp-]+c, %![down-comp-]+c, "
                "%![up-port-]+p, %![down-port-]+p",
@@ -1200,6 +1232,42 @@ bt_graph_add_source_sink_component_ports_connected_listener(
        return BT_GRAPH_STATUS_OK;
 }
 
+enum bt_graph_status
+bt_graph_add_filter_filter_component_ports_connected_listener(
+               struct bt_graph *graph,
+               bt_graph_filter_filter_component_ports_connected_listener_func func,
+               bt_graph_listener_removed_func listener_removed, void *data,
+               int *out_listener_id)
+{
+       struct bt_graph_listener_ports_connected listener = {
+               .base = {
+                       .removed = listener_removed,
+                       .data = data,
+               },
+               .func = (ports_connected_func_t) func,
+       };
+       int listener_id;
+
+       BT_ASSERT_PRE_NON_NULL(graph, "Graph");
+       BT_ASSERT_PRE_NON_NULL(func, "Listener");
+       BT_ASSERT_PRE_NON_NULL(func, "\"Listener removed\" listener");
+       BT_ASSERT_PRE(!graph->in_remove_listener,
+               "Graph currently executing a \"listener removed\" listener: "
+               "%!+g", graph);
+       g_array_append_val(graph->listeners.filter_filter_ports_connected,
+               listener);
+       listener_id = graph->listeners.filter_filter_ports_connected->len - 1;
+       BT_LIB_LOGV("Added \"filter to filter component ports connected\" listener to graph: "
+               "%![graph-]+g, listener-addr=%p, id=%d", graph, listener,
+               listener_id);
+
+       if (listener_id) {
+               *out_listener_id = listener_id;
+       }
+
+       return BT_GRAPH_STATUS_OK;
+}
+
 enum bt_graph_status
 bt_graph_add_filter_sink_component_ports_connected_listener(
                struct bt_graph *graph,
@@ -1308,6 +1376,42 @@ bt_graph_add_source_sink_component_ports_disconnected_listener(
        return BT_GRAPH_STATUS_OK;
 }
 
+enum bt_graph_status
+bt_graph_add_filter_filter_component_ports_disconnected_listener(
+               struct bt_graph *graph,
+               bt_graph_filter_filter_component_ports_disconnected_listener_func func,
+               bt_graph_listener_removed_func listener_removed, void *data,
+               int *out_listener_id)
+{
+       struct bt_graph_listener_ports_disconnected listener = {
+               .base = {
+                       .removed = listener_removed,
+                       .data = data,
+               },
+               .func = (ports_disconnected_func_t) func,
+       };
+       int listener_id;
+
+       BT_ASSERT_PRE_NON_NULL(graph, "Graph");
+       BT_ASSERT_PRE_NON_NULL(func, "Listener");
+       BT_ASSERT_PRE_NON_NULL(func, "\"Listener removed\" listener");
+       BT_ASSERT_PRE(!graph->in_remove_listener,
+               "Graph currently executing a \"listener removed\" listener: "
+               "%!+g", graph);
+       g_array_append_val(graph->listeners.filter_filter_ports_disconnected,
+               listener);
+       listener_id = graph->listeners.filter_filter_ports_disconnected->len - 1;
+       BT_LIB_LOGV("Added \"filter to filter component ports disconnected\" listener to graph: "
+               "%![graph-]+g, listener-addr=%p, id=%d", graph, listener,
+               listener_id);
+
+       if (listener_id) {
+               *out_listener_id = listener_id;
+       }
+
+       return BT_GRAPH_STATUS_OK;
+}
+
 enum bt_graph_status
 bt_graph_add_filter_sink_component_ports_disconnected_listener(
                struct bt_graph *graph,
@@ -1519,6 +1623,10 @@ void bt_graph_notify_ports_connected(struct bt_graph *graph,
        case BT_COMPONENT_CLASS_TYPE_FILTER:
        {
                switch (downstream_comp->class->type) {
+               case BT_COMPONENT_CLASS_TYPE_FILTER:
+                       listeners =
+                               graph->listeners.filter_filter_ports_connected;
+                       break;
                case BT_COMPONENT_CLASS_TYPE_SINK:
                        listeners =
                                graph->listeners.filter_sink_ports_connected;
@@ -1586,6 +1694,10 @@ void bt_graph_notify_ports_disconnected(struct bt_graph *graph,
        case BT_COMPONENT_CLASS_TYPE_FILTER:
        {
                switch (downstream_comp->class->type) {
+               case BT_COMPONENT_CLASS_TYPE_FILTER:
+                       listeners =
+                               graph->listeners.filter_filter_ports_disconnected;
+                       break;
                case BT_COMPONENT_CLASS_TYPE_SINK:
                        listeners =
                                graph->listeners.filter_sink_ports_disconnected;
This page took 0.027589 seconds and 4 git commands to generate.