+
+BT_HIDDEN
+int bt_graph_remove_unconnected_component(struct bt_graph *graph,
+ struct bt_component *component)
+{
+ bt_bool init_can_consume;
+ int64_t count;
+ uint64_t i;
+ int ret = 0;
+
+ BT_ASSERT(graph);
+ BT_ASSERT(component);
+ BT_ASSERT(component->base.ref_count == 0);
+ BT_ASSERT(bt_component_borrow_graph(component) == graph);
+
+ init_can_consume = graph->can_consume;
+ count = bt_component_get_input_port_count(component);
+
+ for (i = 0; i < count; i++) {
+ struct bt_port *port =
+ bt_component_get_input_port_by_index(component, i);
+
+ BT_ASSERT(port);
+ bt_put(port);
+
+ if (bt_port_is_connected(port)) {
+ BT_LOGW("Cannot remove component from graph: "
+ "an input port is connected: "
+ "graph-addr=%p, comp-addr=%p, "
+ "comp-name=\"%s\", connected-port-addr=%p, "
+ "connected-port-name=\"%s\"",
+ graph, component,
+ bt_component_get_name(component),
+ port, bt_port_get_name(port));
+ goto error;
+ }
+ }
+
+ count = bt_component_get_output_port_count(component);
+
+ for (i = 0; i < count; i++) {
+ struct bt_port *port =
+ bt_component_get_output_port_by_index(component, i);
+
+ BT_ASSERT(port);
+ bt_put(port);
+
+ if (bt_port_is_connected(port)) {
+ BT_LOGW("Cannot remove component from graph: "
+ "an output port is connected: "
+ "graph-addr=%p, comp-addr=%p, "
+ "comp-name=\"%s\", connected-port-addr=%p, "
+ "connected-port-name=\"%s\"",
+ graph, component,
+ bt_component_get_name(component),
+ port, bt_port_get_name(port));
+ goto error;
+ }
+ }
+
+ graph->can_consume = BT_FALSE;
+
+ /* Possibly remove from sinks to consume */
+ (void) g_queue_remove(graph->sinks_to_consume, component);
+
+ if (graph->sinks_to_consume->length == 0) {
+ graph->has_sink = BT_FALSE;
+ }
+
+ /*
+ * This calls bt_object_try_spec_release() on the component, and
+ * since its reference count is 0, its destructor is called. Its
+ * destructor calls the user's finalization method (if set).
+ */
+ g_ptr_array_remove(graph->components, component);
+ goto end;
+
+error:
+ ret = -1;
+
+end:
+ graph->can_consume = init_can_consume;
+ return ret;
+}
+
+BT_HIDDEN
+void bt_graph_add_notification(struct bt_graph *graph,
+ struct bt_notification *notif)
+{
+ BT_ASSERT(graph);
+ BT_ASSERT(notif);
+
+ /*
+ * It's okay not to take a reference because, when a
+ * notification's reference count drops to 0, either:
+ *
+ * * It is recycled back to one of this graph's pool.
+ * * It is destroyed because it doesn't have any link to any
+ * graph, which means the original graph is already destroyed.
+ */
+ g_ptr_array_add(graph->notifications, notif);
+}