aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2014-08-11 12:32:56 -0400
committerGlenn Elliott <gelliott@cs.unc.edu>2014-08-11 12:36:13 -0400
commit123cac6d078cfd19ded5ae0342b12dd15c1d2254 (patch)
treede4a6acca22f5008ea2806a0c2cf83dedbc5f0b2
parentcd028d1d0da2a352a7c5ebff551bbbc6f46c2cf8 (diff)
API: Add pgm_is_child() and pgm_is_parent().
This patch adds two new APIs to PGM: pgm_is_child() and pgm_is_parent() for convenience to the programmer. These functions can already be supported by a combination of other PGM API calls, but it is troublesome for such a simple query.
-rw-r--r--include/pgm.h62
-rw-r--r--src/pgm.cpp48
2 files changed, 102 insertions, 8 deletions
diff --git a/include/pgm.h b/include/pgm.h
index 671bb9f..27cae67 100644
--- a/include/pgm.h
+++ b/include/pgm.h
@@ -177,7 +177,7 @@ int pgm_init_graph(graph_t* graph, const char* graph_name);
177/* 177/*
178 Prints the graph in dot format to the provided file descriptor. 178 Prints the graph in dot format to the provided file descriptor.
179 [in] graph: Graph 179 [in] graph: Graph
180 [in] file: File descriptor 180 [in] file: File descriptor
181 Return: 0 on success. -1 on error. 181 Return: 0 on success. -1 on error.
182 */ 182 */
183int pgm_print_graph(graph_t graph, FILE* out); 183int pgm_print_graph(graph_t graph, FILE* out);
@@ -411,16 +411,59 @@ int pgm_get_nr_consume(edge_t edge);
411int pgm_get_nr_threshold(edge_t edge); 411int pgm_get_nr_threshold(edge_t edge);
412 412
413/* 413/*
414 Query to see if 'query' is a child of 'node'.
415 [in] node: possible parent of 'query'
416 [in] query: possible child of 'node'
417 Return:
418 1 if 'query' is a child of 'node'.
419 0 if 'query' is NOT a child of 'node'.
420 -1 if 'query' or 'node' is an invalid node, or
421 if 'query' and 'node' are from different graphs
422
423 Note: Explicit backedges are ignored.
424
425 Note: Beware that pgm_is_child() returns -1 on error,
426 so the code "if(pgm_is_child(..))" may introduce bugs
427 since the logic test does not distinguish between the
428 positive case and the error case.
429 */
430int pgm_is_child(node_t node, node_t query);
431
432/*
433 Query to see if 'query' is a parent of 'node'.
434 [in] node: possible child of 'query'
435 [in] query: possible parent of 'node'
436 Return:
437 1 if 'query' is a parent of 'node'.
438 0 if 'query' is NOT a parent of 'node'.
439 -1 if 'query' or 'node' is an invalid node, or
440 if 'query' and 'node' are from different graphs
441
442 Note: Explicit backedges are ignored.
443
444 Note: Beware that pgm_is_parent() returns -1 on error,
445 so the code "if(pgm_is_parent(..))" may introduce bugs
446 since the logic test does not distinguish between the
447 positive case and the error case.
448 */
449int pgm_is_parent(node_t node, node_t query);
450
451/*
414 Query to see if 'query' is an ancestor of 'node'. 452 Query to see if 'query' is an ancestor of 'node'.
415 [in] node: possible decendent of 'query' 453 [in] node: possible decendent of 'query'
416 [in] query: possible ancestor of 'node' 454 [in] query: possible ancestor of 'node'
417 Return: 455 Return:
418 1 if 'query' is an ancestor of 'node'. 456 1 if 'query' is an ancestor of 'node'.
419 0 if 'query' is NOT an ancestor of 'node'. 457 0 if 'query' is NOT an ancestor of 'node'.
420 -1 if 'query' or 'node' is an invalid node, or 458 -1 if 'query' or 'node' is an invalid node, or
421 if 'query' and 'node' are from different graphs 459 if 'query' and 'node' are from different graphs
422 460
423 Note: pgm_is_ancestor(n, q) === pgm_is_descendant(q, n) 461 Note: Explicit backedges are ignored.
462
463 Note: Beware that pgm_is_ancestor() returns -1 on error,
464 so the code "if(pgm_is_ancestor(..))" may introduce bugs
465 since the logic test does not distinguish between the
466 positive case and the error case.
424 */ 467 */
425int pgm_is_ancestor(node_t node, node_t query); 468int pgm_is_ancestor(node_t node, node_t query);
426 469
@@ -431,18 +474,23 @@ int pgm_is_ancestor(node_t node, node_t query);
431 Return: 474 Return:
432 1 if 'query' is an decendent of 'node'. 475 1 if 'query' is an decendent of 'node'.
433 0 if 'query' is NOT an decendent of 'node'. 476 0 if 'query' is NOT an decendent of 'node'.
434 -1 if 'query' or 'node' is an invalid node, or 477 -1 if 'query' or 'node' is an invalid node, or
435 if 'query' and 'node' are from different graphs 478 if 'query' and 'node' are from different graphs
436 479
437 Note: pgm_is_ancestor(n, q) === pgm_is_descendant(q, n) 480 Note: Explicit backedges are ignored.
481
482 Note: Beware that pgm_is_descendant() returns -1 on error,
483 so the code "if(pgm_is_descendant(..))" may introduce bugs
484 since the logic test does not distinguish between the
485 positive case and the error case.
438 */ 486 */
439int pgm_is_descendant(node_t node, node_t query); 487int pgm_is_descendant(node_t node, node_t query);
440 488
441/* 489/*
442 Check if a graph is a acyclic. 490 Check if a graph is a acyclic.
443 [in] graph: Graph descriptor 491 [in] graph: Graph descriptor
444 [in] ignore_explicit_backedges: Ignore edges that were added 492 [in] ignore_explicit_backedges: Ignore edges that were added
445 with pgm_init_backedge(). 493 with pgm_init_backedge().
446 Return: 1 if graph is acyclic, 0 if it is not. 494 Return: 1 if graph is acyclic, 0 if it is not.
447 */ 495 */
448int pgm_is_dag(graph_t graph, int ignore_explicit_backedges = 1); 496int pgm_is_dag(graph_t graph, int ignore_explicit_backedges = 1);
diff --git a/src/pgm.cpp b/src/pgm.cpp
index d66641f..122775e 100644
--- a/src/pgm.cpp
+++ b/src/pgm.cpp
@@ -2723,6 +2723,53 @@ out:
2723 return ret; 2723 return ret;
2724} 2724}
2725 2725
2726int pgm_is_parent(node_t node, node_t query)
2727{
2728 int ret = -1;
2729 struct pgm_graph* g;
2730 struct pgm_node* n;
2731 struct pgm_node* q;
2732
2733 if(node.graph != query.graph)
2734 goto out;
2735 if(!is_valid_graph(node.graph))
2736 goto out;
2737
2738 ret = 0;
2739 if(node.node == query.node)
2740 {
2741 goto out;
2742 }
2743
2744 g = &gGraphs[node.graph];
2745 n = &g->nodes[node.node];
2746 q = &g->nodes[query.node];
2747
2748 pthread_mutex_lock(&g->lock);
2749 for(int i = 0; i < n->nr_in; ++i)
2750 {
2751 if(g->edges[n->in[i]].is_backedge)
2752 {
2753 continue; // skip backedge
2754 }
2755
2756 if(q == &g->nodes[g->edges[n->in[i]].producer])
2757 {
2758 ret = 1;
2759 break;
2760 }
2761 }
2762 pthread_mutex_unlock(&g->lock);
2763
2764out:
2765 return ret;
2766}
2767
2768int pgm_is_child(node_t node, node_t query)
2769{
2770 return pgm_is_parent(query, node);
2771}
2772
2726static int is_ancestor(const struct pgm_graph* g, 2773static int is_ancestor(const struct pgm_graph* g,
2727 const struct pgm_node* n, const struct pgm_node* q, 2774 const struct pgm_node* n, const struct pgm_node* q,
2728 std::set<int>& visited) 2775 std::set<int>& visited)
@@ -2785,7 +2832,6 @@ int pgm_is_ancestor(node_t node, node_t query)
2785 2832
2786out: 2833out:
2787 return ret; 2834 return ret;
2788
2789} 2835}
2790 2836
2791int pgm_is_descendant(node_t n, node_t query) 2837int pgm_is_descendant(node_t n, node_t query)