aga.h 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /* Licensed under LGPLv2+ - see LICENSE file for details */
  2. #ifndef CCAN_AGA_H
  3. #define CCAN_AGA_H
  4. /*
  5. * Abstract Graph Algorithms
  6. *
  7. * This module implements several standard algorithms on "abstract"
  8. * (directed) graphs. That is to say rather than requiring a specific
  9. * concrete representation of the graph, user-supplied callbacks allow
  10. * the graph to be constructed as it is explored.
  11. *
  12. *
  13. * Node representation
  14. * ===================
  15. *
  16. * Graph nodes are represented by 'struct aga_node'
  17. *
  18. * - These will often be embedded in a caller-specific structure
  19. * (calling code can then locate its own structures using
  20. * container_of)
  21. *
  22. * - Nodes are semi-persistent - they MAY be constructed on the fly by
  23. * the edge_info callback (see below), but MUST then remain in place
  24. * at least as long as the completion of the current graph
  25. * algorithm.
  26. *
  27. * - Nodes must be initialized with aga_node_init(), either up front,
  28. * or as they are constructed on the fly.
  29. *
  30. * - The contents of the structure should be treated as opaque by the
  31. * caller.
  32. *
  33. *
  34. * Edge representation
  35. * ===================
  36. *
  37. * Graph edges are reported by three caller supplied functions,
  38. * 'first_edge', 'next_edge' and 'edge_info'.
  39. *
  40. * - Edges are identified by a (void *)
  41. * - The combination of a graph, a node and this (void *) MUST
  42. * uniquely identify an edge
  43. * - Different edges leading from different nodes MAY have the same
  44. * (void *) identifier
  45. * - NULL has a special meaning (indicating there are no more edges
  46. * from a given node).
  47. * - Otherwise, edge identifiers are treated as opaque by aga
  48. *
  49. * - Calling first_edge, followed by next_edge repeatedly must iterate
  50. * through all the edges leading from node n.
  51. *
  52. * - Either first_edge or next_edge may return NULL indicating there
  53. * are no further edges from this node
  54. *
  55. * - edge_info MAY return a negative value in case of error. This
  56. * will generally abort any aga algorithm which encounters it.
  57. *
  58. * - Otherwise edge_info must return 0. Any other return value will
  59. * cause an abort().
  60. *
  61. * - edge_info MAY set ei->to to NULL, indicating a "missing" edge,
  62. * thus there MAY be more edge identifiers than actual edges from a
  63. * given node. Otherwise, edge_info MUST fill in the ei->to field
  64. * with a pointer to the destination node of the given edge
  65. *
  66. * - The ei->to field for a returned edge MAY point to an existing
  67. * struct aga_node, or it MAY have just been allocated by the edge
  68. * callback itself. If the latter, it MUST have been initialized
  69. * with aga_node_init() before the edge callback returns.
  70. *
  71. * - If a node is contructed by the edge callback, any subsequent
  72. * reference to that node by the edge callback for *any* node and
  73. * index MUST use the same pointer.
  74. *
  75. * Concurrency
  76. * ===========
  77. *
  78. * - Because the algorithms implemented here keep state in the
  79. * aga_node structures, only one algorithm can run at a time.
  80. * Global state for algorithms is stored in the aga_graph structure.
  81. *
  82. * - When you start an algorithm (aga_*_start()) the graph is marked
  83. * as in-use.
  84. *
  85. * - Subsequent attempts to start an algorithm will fail;
  86. * aga_*_start() will return -1.
  87. *
  88. * - To release the graph for another algorithm, use aga_finish().
  89. *
  90. * - Calling functions associated with one algorithm while another is
  91. * running has undefined results.
  92. *
  93. * Errors
  94. * ======
  95. *
  96. * - Errors may be reported by the edge_info callback, or may be
  97. * detected internally by algorithms.
  98. *
  99. * - Algorithms will generally stop running when they encounter an
  100. * error; the call which detects the error and subsequent calls will
  101. * return a "safe", but otherwise meaningless value.
  102. *
  103. * - After an error is encountered aga_error() will return a non-zero
  104. * value. Negative values are reserved for errors reported by the
  105. * user supplied edge callback. Positive values are reserved for
  106. * errors detected interally by aga.
  107. *
  108. * - Errors are cleared on aga_finish().
  109. */
  110. #include "config.h"
  111. #include <string.h>
  112. #include <ccan/build_assert/build_assert.h>
  113. #include <ccan/check_type/check_type.h>
  114. #include <ccan/lstack/lstack.h>
  115. #include <ccan/lqueue/lqueue.h>
  116. struct aga_graph;
  117. struct aga_node;
  118. /*
  119. * Callbacks
  120. */
  121. typedef const void *(*aga_first_edge_fn)(const struct aga_graph *g,
  122. const struct aga_node *n);
  123. typedef const void *(*aga_next_edge_fn)(const struct aga_graph *g,
  124. const struct aga_node *n,
  125. const void *e);
  126. struct aga_edge_info {
  127. struct aga_node *to;
  128. };
  129. typedef int (*aga_edge_info_fn)(const struct aga_graph *g,
  130. const struct aga_node *n,
  131. const void *e, struct aga_edge_info *ei);
  132. /*
  133. * Internal data structures
  134. */
  135. struct aga_node {
  136. int sequence;
  137. union {
  138. struct {
  139. struct lstack_link parent;
  140. const void *edge;
  141. } dfs;
  142. struct {
  143. struct lqueue_link next;
  144. const void *edge;
  145. } bfs;
  146. } u;
  147. };
  148. struct aga_graph {
  149. int sequence;
  150. int error;
  151. aga_first_edge_fn first_edge;
  152. aga_next_edge_fn next_edge;
  153. aga_edge_info_fn edge_info;
  154. };
  155. /*
  156. * Core functions
  157. */
  158. /**
  159. * aga_init_graph - Initialize a new abstract graph
  160. * @g: graph structure to initialize
  161. * @first_edge: first edge callback
  162. * @next_edge: next edge callback
  163. * @edge_into: edge info callback
  164. *
  165. * Initialize @g to represent an abstract graph defined by the
  166. * supplied edge callbacks
  167. */
  168. void aga_init_graph_(struct aga_graph *g,
  169. aga_first_edge_fn first_edge,
  170. aga_next_edge_fn next_edge,
  171. aga_edge_info_fn edge_info);
  172. #define aga_init_graph(g_, fefn_, nefn_, eifn_) \
  173. do { \
  174. struct aga_node *n_; \
  175. struct aga_edge_info *ei_; \
  176. BUILD_ASSERT(check_types_match((fefn_)((g_), n_), \
  177. (nefn_)((g_), n_, \
  178. (fefn_)((g_), n_))) \
  179. == 0); \
  180. BUILD_ASSERT(check_type((eifn_)((g_), n_, \
  181. (fefn_)((g_), n_), ei_), \
  182. int) == 0); \
  183. aga_init_graph_((g_), (aga_first_edge_fn)(fefn_), \
  184. (aga_next_edge_fn)(nefn_), \
  185. (aga_edge_info_fn)(eifn_)); \
  186. } while (0)
  187. /**
  188. * enum aga_error - Error codes for aga routines
  189. *
  190. * These error codes are returned by aga_error() for errors detected
  191. * within aga itself (rather than errors reported by supplied
  192. * callbacks, which should be negative
  193. */
  194. enum aga_error {
  195. /* No error */
  196. AGA_ERR_NONE = 0,
  197. };
  198. /**
  199. * aga_error - Determine error state of a graph
  200. * @g: the graph
  201. *
  202. * Returns 0 if the graph is not in an error state, negative values
  203. * for error states reported by one of the edge callbacks and
  204. * postitive values for errors detected by aga itself.
  205. */
  206. int aga_error(const struct aga_graph *g);
  207. /**
  208. * aga_node_init - Initialize a graph node
  209. * @node: a graph node
  210. *
  211. * Initialize @node as a new graph node. This must be called before
  212. * @node is passed to any aga function, or returned from an edge_info
  213. * callback (in the ei->to field)
  214. */
  215. static inline void aga_node_init(struct aga_node *node)
  216. {
  217. memset(node, 0, sizeof(*node));
  218. }
  219. /**
  220. * aga_finish - Finish an aga algorithm
  221. * @g: graph
  222. *
  223. * Wraps up the aga algorithm currently running on @g. This will
  224. * clear any error conditions. After this is called it is an error to
  225. * call aga functions on @g apart from aga_*_start() and aga_error.
  226. */
  227. void aga_finish(struct aga_graph *g);
  228. const void *aga_first_edge(const struct aga_graph *g, const struct aga_node *n);
  229. const void *aga_next_edge(const struct aga_graph *g, const struct aga_node *n,
  230. const void *e);
  231. int aga_edge_info(const struct aga_graph *g, const struct aga_node *n,
  232. const void *e, struct aga_edge_info *ei);
  233. #define aga_for_each_edge(_e, _g, _n) \
  234. for ((_e) = aga_first_edge((_g), (_n)); (_e); \
  235. (_e) = aga_next_edge((_g), (_n), (_e)))
  236. #define aga_for_each_edge_info(_e, _ei, _err, _g, _n) \
  237. for ((_err) = 0, (_e) = aga_first_edge((_g), (_n)); \
  238. (_e) && ((((_err) = aga_edge_info((_g), (_n), (_e), &(_ei)))) == 0); \
  239. (_e) = aga_next_edge((_g), (_n), (_e))) \
  240. if ((_ei).to)
  241. /*
  242. * Depth first search
  243. */
  244. /**
  245. * aga_dfs_start - Start a depth-first search
  246. * @g: graph to search
  247. *
  248. * Begins the depth-first search algorithm on @g
  249. */
  250. int aga_dfs_start(struct aga_graph *g);
  251. /**
  252. * aga_dfs_explore - One step of depth-first search
  253. * @g: graph to search
  254. * @n: node to start exploration from
  255. *
  256. * If @n has not yet been explored since aga_dfs_start(), returns @n.
  257. * Otherwise returns the next node after @n in depth-first search
  258. * order. Marks the returned node as explored.
  259. */
  260. struct aga_node *aga_dfs_explore(struct aga_graph *g, struct aga_node *n);
  261. /**
  262. * aga_dfs - Depth-first search
  263. * @_n: pointer to current node (output)
  264. * @_g: graph to search
  265. * @_start: node to start from
  266. *
  267. * Performs a depth first search. The block following this macro is
  268. * executed with @_n set first to @_start, then to each node reachable
  269. * from @_start in depth first search order.
  270. *
  271. * aga_dfs_start() must be called before this macro is used.
  272. */
  273. #define aga_dfs(_n, _g, _start) \
  274. for ((_n) = (_start); ((_n) = aga_dfs_explore((_g), (_n))) != NULL; )
  275. /*
  276. * Breadth first search
  277. */
  278. /**
  279. * aga_bfs_start - Start a breadth-first search
  280. * @g: graph to search
  281. *
  282. * Begins the breadth-first search algorithm on @g
  283. */
  284. int aga_bfs_start(struct aga_graph *g);
  285. /**
  286. * aga_bfs_explore - One step of breadth-first search
  287. * @g: graph to search
  288. * @n: node to start exploration from
  289. *
  290. * If @n has not yet been explored since aga_bfs_start(), returns @n.
  291. * Otherwise returns the next node after @n in breadth-first search
  292. * order. Marks the returned node as explored.
  293. */
  294. struct aga_node *aga_bfs_explore(struct aga_graph *g, struct aga_node *n);
  295. /**
  296. * aga_bfs - Breadth-first search
  297. * @_n: pointer to current node (output)
  298. * @_g: graph to search
  299. * @_start: node to start from
  300. *
  301. * Performs a breadth first search. The block following this macro is
  302. * executed with @_n set first to @_start, then to each node reachable
  303. * from @_start in depth first search order.
  304. *
  305. * aga_bfs_start() must be called before this macro is used.
  306. */
  307. #define aga_bfs(_n, _g, _start) \
  308. for ((_n) = (_start) ; ((_n) = aga_bfs_explore((_g), (_n))) != NULL; )
  309. #endif /* CCAN_AGA_H */