[pulseaudio-discuss] [PATCH 09/15] node: Delete edges when unlinking a node

Tanu Kaskinen tanu.kaskinen at linux.intel.com
Thu Feb 13 19:35:54 CET 2014


Nodes need to keep track of the edges that they are part of, so that
a node knows which edges to delete when the node is unlinked.
---
 src/pulsecore/edge.c | 33 +++++++++++++++++++++++++++++++++
 src/pulsecore/edge.h |  2 ++
 src/pulsecore/node.c | 28 ++++++++++++++++++++++++++++
 src/pulsecore/node.h |  6 ++++++
 4 files changed, 69 insertions(+)

diff --git a/src/pulsecore/edge.c b/src/pulsecore/edge.c
index da40a53..931bee1 100644
--- a/src/pulsecore/edge.c
+++ b/src/pulsecore/edge.c
@@ -32,6 +32,9 @@
 
 #include <pulse/xmalloc.h>
 
+static int edge_put(pa_edge *edge);
+static void edge_unlink(pa_edge *edge);
+
 uint64_t pa_edge_key(uint32_t input_index, uint32_t output_index) {
     return ((uint64_t) input_index) << 32 | (uint64_t) output_index;
 }
@@ -116,6 +119,8 @@ pa_edge *pa_edge_new(pa_node *input, pa_node *output, int *ret) {
     edge->output = output;
     edge->string = pa_sprintf_malloc("%s -> %s", input->name, output->name);
 
+    edge_put(edge);
+
     return edge;
 
 fail:
@@ -128,9 +133,37 @@ fail:
     return NULL;
 }
 
+static int edge_put(pa_edge *edge) {
+    pa_assert(edge);
+
+    pa_node_add_edge(edge->input, edge);
+    pa_node_add_edge(edge->output, edge);
+
+    pa_log_debug("Created edge %s.", edge->string);
+
+    return 0;
+}
+
+static void edge_unlink(pa_edge *edge) {
+    pa_assert(edge);
+
+    if (edge->unlinked) {
+        pa_log_debug("Unlinking edge %s (already unlinked, this is a no-op).", edge->string);
+        return;
+    }
+
+    edge->unlinked = true;
+
+    pa_log_debug("Unlinking edge %s.", edge->string);
+
+    pa_node_remove_edge(edge->output, edge);
+    pa_node_remove_edge(edge->input, edge);
+}
+
 void pa_edge_free(pa_edge *edge) {
     pa_assert(edge);
 
+    edge_unlink(edge);
     pa_xfree(edge->string);
     pa_xfree(edge);
 }
diff --git a/src/pulsecore/edge.h b/src/pulsecore/edge.h
index 880df90..bd5cca1 100644
--- a/src/pulsecore/edge.h
+++ b/src/pulsecore/edge.h
@@ -36,6 +36,8 @@ struct pa_edge {
     pa_node *input;
     pa_node *output;
     char *string;
+
+    bool unlinked;
 };
 
 #define PA_MAX_EDGES 1024
diff --git a/src/pulsecore/node.c b/src/pulsecore/node.c
index c0408c2..2475c85 100644
--- a/src/pulsecore/node.c
+++ b/src/pulsecore/node.c
@@ -25,6 +25,7 @@
 #endif
 
 #include <pulsecore/core-util.h>
+#include <pulsecore/edge.h>
 #include <pulsecore/namereg.h>
 #include <pulsecore/strbuf.h>
 
@@ -145,6 +146,7 @@ pa_node *pa_node_new(pa_core *core, pa_node_new_data *data) {
     n->type = data->type;
     n->direction = data->direction;
     n->monitor_of = data->monitor_of;
+    n->edges = pa_hashmap_new(NULL, NULL);
     n->active = data->active;
 
     return n;
@@ -161,6 +163,11 @@ void pa_node_free(pa_node *node) {
 
     pa_node_unlink(node);
 
+    if (node->edges) {
+        pa_assert(pa_hashmap_isempty(node->edges));
+        pa_hashmap_free(node->edges);
+    }
+
     pa_xfree(node->description);
 
     if (node->name) {
@@ -404,6 +411,8 @@ int pa_node_put(pa_node *node, pa_node **requested_connections, unsigned n_reque
 }
 
 void pa_node_unlink(pa_node *node) {
+    pa_edge *edge;
+
     pa_assert(node);
 
     if (node->unlinked) {
@@ -415,6 +424,11 @@ void pa_node_unlink(pa_node *node) {
 
     pa_log_debug("Unlinking node %s.", node->name);
 
+    while ((edge = pa_hashmap_steal_first(node->edges))) {
+        pa_log_debug("Deleting edge %s due to unlinking one of its endpoints.", edge->string);
+        pa_core_delete_edge(node->core, edge);
+    }
+
     if (node->monitor_of)
         node->monitor_of->monitor = NULL;
 
@@ -425,6 +439,20 @@ void pa_node_unlink(pa_node *node) {
 
 }
 
+int pa_node_add_edge(pa_node *node, pa_edge *edge) {
+    pa_assert(node);
+    pa_assert(edge);
+
+    return pa_hashmap_put(node->edges, edge, edge);
+}
+
+int pa_node_remove_edge(pa_node *node, pa_edge *edge) {
+    pa_assert(node);
+    pa_assert(edge);
+
+    return pa_hashmap_remove(node->edges, edge) ? 0 : -1;
+}
+
 void pa_node_active_changed(pa_node *node, bool new_active) {
     pa_assert(node);
 
diff --git a/src/pulsecore/node.h b/src/pulsecore/node.h
index 1014f16..626ee2f 100644
--- a/src/pulsecore/node.h
+++ b/src/pulsecore/node.h
@@ -23,6 +23,8 @@
   USA.
 ***/
 
+#include <pulsecore/hashmap.h>
+
 typedef struct pa_node_new_data pa_node_new_data;
 typedef struct pa_node pa_node;
 
@@ -69,6 +71,7 @@ struct pa_node {
 
     pa_node *monitor;
     pa_node *monitor_of;
+    pa_hashmap *edges; /* pa_edge -> pa_edge (hashmap-as-a-set) */
     bool active;
 
     bool unlinked;
@@ -101,6 +104,9 @@ void pa_node_free(pa_node *node);
 int pa_node_put(pa_node *node, pa_node **requested_connections, unsigned n_requested_connections);
 void pa_node_unlink(pa_node *node);
 
+int pa_node_add_edge(pa_node *node, pa_edge *edge);
+int pa_node_remove_edge(pa_node *node, pa_edge *edge);
+
 /* To be called by the node back end when its active state changes. */
 void pa_node_active_changed(pa_node *node, bool new_active);
 
-- 
1.8.3.1



More information about the pulseaudio-discuss mailing list