]> git.ozlabs.org Git - ccan/blobdiff - ccan/aga/aga.c
aga: Abstract Graph Algorithms
[ccan] / ccan / aga / aga.c
diff --git a/ccan/aga/aga.c b/ccan/aga/aga.c
new file mode 100644 (file)
index 0000000..f27f9f3
--- /dev/null
@@ -0,0 +1,93 @@
+/* Licensed under LGPLv2+ - see LICENSE file for details */
+#include "config.h"
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <ccan/aga/aga.h>
+
+#include "private.h"
+
+void aga_init_graph_(struct aga_graph *g,
+                    aga_first_edge_fn first_edge,
+                    aga_next_edge_fn next_edge,
+                    aga_edge_info_fn edge_info)
+{
+       g->sequence = 0;
+       g->error = 0;
+
+       g->first_edge = first_edge;
+       g->next_edge = next_edge;
+       g->edge_info = edge_info;
+}
+
+int aga_error(const struct aga_graph *g)
+{
+       return g->error;
+}
+
+void aga_fail(struct aga_graph *g, int error)
+{
+       g->error = error;
+}
+
+int aga_start(struct aga_graph *g)
+{
+       if (g->sequence & 1) /* Odd means someone's already running */
+               return -1;
+       assert(g->error == 0);
+       /* FIXME: Want an atomic cmpxchg to make this thread safe */
+       ++g->sequence;
+       return 0;
+}
+
+bool aga_check_state(const struct aga_graph *g)
+{
+       if (!(g->sequence & 1))
+               return false; /* No algo in progress */
+       if (g->error)
+               return false; /* error state */
+       return true;
+}
+
+void aga_finish(struct aga_graph *g)
+{
+       assert(g->sequence & 1);
+       g->error = 0;
+       g->sequence++;
+}
+
+bool aga_update_node(const struct aga_graph *g, struct aga_node *node)
+{
+       if (node->sequence == g->sequence)
+               return false;
+
+       node->sequence = g->sequence;
+       return true;
+}
+
+const void *aga_first_edge(const struct aga_graph *g, const struct aga_node *n)
+{
+       return g->first_edge(g, n);
+}
+
+const void *aga_next_edge(const struct aga_graph *g, const struct aga_node *n,
+                         const void *e)
+{
+       if (!e)
+               return NULL;
+       else
+               return g->next_edge(g, n, e);
+}
+
+int aga_edge_info(const struct aga_graph *g, const struct aga_node *n,
+                 const void *e, struct aga_edge_info *ei)
+{
+       int rc;
+
+       ei->to = NULL;
+       rc = g->edge_info(g, n, e, ei);
+       assert(rc <= 0);
+       return rc;
+}