+static
+int muxer_upstream_notif_iter_next(struct muxer_notif_iter *muxer_notif_iter,
+ struct muxer_upstream_notif_iter *muxer_upstream_notif_iter)
+{
+ int ret = 0;
+ enum bt_notification_iterator_status next_status;
+
+ next_status = bt_notification_iterator_next(
+ muxer_upstream_notif_iter->notif_iter);
+
+ switch (next_status) {
+ case BT_NOTIFICATION_ITERATOR_STATUS_OK:
+ /* Everything okay */
+ break;
+ case BT_NOTIFICATION_ITERATOR_STATUS_AGAIN:
+ muxer_notif_iter_add_upstream_notif_iter_to_retry(
+ muxer_notif_iter, muxer_upstream_notif_iter);
+ break;
+ case BT_NOTIFICATION_ITERATOR_STATUS_END:
+ /*
+ * Notification iterator reached the end: release it. It
+ * won't be considered again to find the youngest
+ * notification.
+ */
+ BT_PUT(muxer_upstream_notif_iter->notif_iter);
+ goto end;
+ default:
+ /* Error or unsupported status code */
+ ret = next_status;
+ }
+
+end:
+ return ret;
+}
+
+static
+int muxer_notif_iter_handle_newly_connected_ports(struct muxer_comp *muxer_comp,
+ struct muxer_notif_iter *muxer_notif_iter)
+{
+ struct bt_component *comp = NULL;
+ int ret = 0;
+
+ comp = bt_component_from_private_component(muxer_comp->priv_comp);
+ assert(comp);
+
+ /*
+ * Here we create one upstream notification iterator for each
+ * newly connected port. The list of newly connected ports to
+ * handle here is updated by muxer_port_connected().
+ *
+ * An initial "next" operation is performed on each new upstream
+ * notification iterator. The possible return values of this
+ * initial "next" operation are:
+ *
+ * * BT_NOTIFICATION_ITERATOR_STATUS_OK: Perfect, we have a
+ * current notification.
+ *
+ * * BT_NOTIFICATION_ITERATOR_STATUS_AGAIN: No notification so
+ * far, but the muxer upstream notification iterator is added
+ * to the list of upstream notification iterators to retry
+ * before finding the next youngest notification.
+ *
+ * * BT_NOTIFICATION_ITERATOR_STATUS_END: No notification, and
+ * we immediately release the upstream notification iterator
+ * because it's useless.
+ *
+ * A possible side effect of this initial "next" operation, on
+ * each notification iterator, is the connection of a new port.
+ * In this case the list of newly connected ports is updated and
+ * this loop continues.
+ *
+ * Once this loop finishes successfully, the set of upstream
+ * notification iterators is considered _stable_, that is, it is
+ * safe, if no notification iterators must be retried, to select
+ * the youngest notification amongst them to be returned by the
+ * next "next" method call.
+ */
+ while (true) {
+ GList *node = muxer_notif_iter->newly_connected_priv_ports;
+ struct bt_private_port *priv_port;
+ struct bt_port *port;
+ struct bt_notification_iterator *upstream_notif_iter = NULL;
+ struct muxer_upstream_notif_iter *muxer_upstream_notif_iter;
+
+ if (!node) {
+ break;
+ }
+
+ priv_port = node->data;
+ port = bt_port_from_private_port(priv_port);
+ assert(port);
+
+ if (!bt_port_is_connected(port)) {
+ /*
+ * Looks like this port is not connected
+ * anymore: we can't create an upstream
+ * notification iterator on its connection in
+ * this case.
+ */
+ goto remove_node;
+ }
+
+ BT_PUT(port);
+ upstream_notif_iter = create_notif_iter_on_input_port(priv_port,
+ &ret);
+ if (ret) {
+ assert(!upstream_notif_iter);
+ bt_put(priv_port);
+ goto error;
+ }
+
+ muxer_upstream_notif_iter =
+ muxer_notif_iter_add_upstream_notif_iter(
+ muxer_notif_iter, upstream_notif_iter,
+ priv_port);
+ BT_PUT(priv_port);
+ BT_PUT(upstream_notif_iter);
+ if (!muxer_upstream_notif_iter) {
+ goto error;
+ }
+
+ ret = muxer_upstream_notif_iter_next(muxer_notif_iter,
+ muxer_upstream_notif_iter);
+ if (ret) {
+ goto error;
+ }
+
+remove_node:
+ bt_put(upstream_notif_iter);
+ bt_put(port);
+ bt_put(priv_port);
+ muxer_notif_iter->newly_connected_priv_ports =
+ g_list_delete_link(
+ muxer_notif_iter->newly_connected_priv_ports,
+ node);
+ }
+
+ goto end;
+
+error:
+ if (ret == 0) {
+ ret = -1;
+ }
+
+end:
+ bt_put(comp);
+ return ret;
+}
+