Interface Documentation
Version: invalid
point_walker.hh
Go to the documentation of this file.
1 /*
2  @@@@@@@@ @@ @@@@@@ @@@@@@@@ @@
3  /@@///// /@@ @@////@@ @@////// /@@
4  /@@ /@@ @@@@@ @@ // /@@ /@@
5  /@@@@@@@ /@@ @@///@@/@@ /@@@@@@@@@/@@
6  /@@//// /@@/@@@@@@@/@@ ////////@@/@@
7  /@@ /@@/@@//// //@@ @@ /@@/@@
8  /@@ @@@//@@@@@@ //@@@@@@ @@@@@@@@ /@@
9  // /// ////// ////// //////// //
10 
11  Copyright (c) 2016, Triad National Security, LLC
12  All rights reserved.
13  */
14 #pragma once
15 
18 #include <flecsi-config.h>
19 
20 #include "flecsi/flog.hh"
21 #include "flecsi/util/constant.hh"
22 #include "flecsi/util/dag.hh"
24 
25 #if defined(FLECSI_ENABLE_GRAPHVIZ)
26 #include "flecsi/util/graphviz.hh"
27 #endif
28 
29 #include <map>
30 #include <vector>
31 
32 namespace flecsi {
33 namespace ctrl_impl {
34 
45 template<bool (*Predicate)(), typename... ControlPoints>
46 struct cycle {
47 
48  using type = std::tuple<ControlPoints...>;
49  static constexpr size_t last = std::tuple_size<type>::value - 1;
50 
51  template<size_t E, typename T>
52  struct recurse;
53 
54  template<size_t E, bool (*P)(), typename... CPs>
56  using type = std::tuple<CPs...>;
57  static constexpr const auto & value =
59  };
60 
61  template<size_t E, auto Value>
63  static constexpr const auto & value = Value;
64  };
65 
66  static constexpr auto & begin =
68  static constexpr auto & end =
70 
71  static bool predicate() {
72  return Predicate();
73  } // run
74 
75 }; // struct cycle
76 
77 /*
78  Helper type to initialize dag labels.
79  */
80 
81 template<typename ControlPolicy>
82 struct init_walker : public util::tuple_walker<init_walker<ControlPolicy>> {
83 
84  using control_points_enum = typename ControlPolicy::control_points_enum;
86 
87  init_walker(std::map<control_points_enum, dag> & registry)
88  : registry_(registry) {}
89 
90  template<typename ElementType>
91  void visit_type() {
92 
93  if constexpr(std::is_same<typename ElementType::type,
94  control_points_enum>::value) {
95  registry_.try_emplace(ElementType::value, *ElementType::value);
96  }
97  else {
98  init_walker(registry_).template walk_types<typename ElementType::type>();
99  } // while
100  } // visit_type
101 
102 private:
103  std::map<control_points_enum, dag> & registry_;
104 
105 }; // struct init_walker
106 
114 template<typename ControlPolicy>
115 struct point_walker : public util::tuple_walker<point_walker<ControlPolicy>> {
116 
117  using control_points_enum = typename ControlPolicy::control_points_enum;
118  using node_type = typename ControlPolicy::node_type;
119 
120  point_walker(
121  std::map<control_points_enum, std::vector<node_type const *>> sorted,
122  int & exit_status)
123  : sorted_(sorted), exit_status_(exit_status) {}
124 
134  template<typename ElementType>
135  void visit_type() {
136 
137  if constexpr(std::is_same<typename ElementType::type,
138  control_points_enum>::value) {
139 
140  // This is not a cycle -> execute each action for this control point.
141  for(auto & node : sorted_[ElementType::value]) {
142  exit_status_ |= node->execute();
143  } // for
144  }
145  else {
146  // This is a cycle -> create a new control point walker to recurse
147  // the cycle.
148  while(ElementType::predicate()) {
149  point_walker walker(sorted_, exit_status_);
150  walker.template walk_types<typename ElementType::type>();
151  } // while
152  } // if
153  } // visit_type
154 
155 private:
156  std::map<control_points_enum, std::vector<node_type const *>> sorted_;
157  int & exit_status_;
158 
159 }; // struct point_walker
160 
161 #if defined(FLECSI_ENABLE_GRAPHVIZ)
162 
163 template<typename ControlPolicy>
164 struct point_writer
165  : public flecsi::util::tuple_walker<point_writer<ControlPolicy>> {
166  using control_points_enum = typename ControlPolicy::control_points_enum;
167  using node_type = typename ControlPolicy::node_type;
169  using graphviz = flecsi::util::graphviz;
170 
171  static constexpr const char * colors[4] = {"#77c3ec",
172  "#b8e2f2",
173  "#4eb2e0",
174  "#9dd9f3"};
175 
176  point_writer(std::map<control_points_enum, dag> registry,
177  graphviz & gv,
178  int depth = 0)
179  : registry_(registry), gv_(gv), depth_(depth) {}
180 
181  template<typename ElementType>
182  void visit_type() {
183  if constexpr(std::is_same<typename ElementType::type,
184  control_points_enum>::value) {
185  auto & dag = registry_[ElementType::value];
186 
187  auto * root = gv_.add_node(dag.label().c_str(), dag.label().c_str());
188  gv_.set_node_attribute(root, "shape", "box");
189  gv_.set_node_attribute(root, "style", "rounded");
190 
191  if(size_t(ElementType::value) > 0) {
192  auto & last = registry_[static_cast<control_points_enum>(
193  static_cast<size_t>(ElementType::value) - 1)];
194  auto * last_node = gv_.node(last.label().c_str());
195  auto * edge = gv_.add_edge(last_node, root);
196  gv_.set_edge_attribute(edge, "color", "#1d76db");
197  gv_.set_edge_attribute(edge, "fillcolor", "#1d76db");
198  gv_.set_edge_attribute(edge, "style", "bold");
199  } // if
200 
201  dag.add(gv_, colors[static_cast<size_t>(ElementType::value) % 4]);
202 
203  for(auto & n : dag) {
204  if(n->size() == 0) {
205  auto * edge = gv_.add_edge(root, gv_.node(n->identifier().c_str()));
206  gv_.set_edge_attribute(edge, "penwidth", "1.5");
207  } // if
208  } // for
209  }
210  else {
211  point_writer(registry_, gv_, depth_ - 1)
212  .template walk_types<typename ElementType::type>();
213 
214  auto & begin = registry_[ElementType::begin];
215  auto & end = registry_[ElementType::end];
216 
217  auto * edge = gv_.add_edge(
218  gv_.node(end.label().c_str()), gv_.node(begin.label().c_str()));
219 
220  gv_.set_edge_attribute(edge, "label", " cycle");
221  gv_.set_edge_attribute(edge, "color", "#1d76db");
222  gv_.set_edge_attribute(edge, "fillcolor", "#1d76db");
223  gv_.set_edge_attribute(edge, "style", "dashed,bold");
224 
225  if constexpr(ElementType::begin == ElementType::end) {
226  gv_.set_edge_attribute(edge, "dir", "back");
227  }
228  else {
229  if(depth_ < 0) {
230  gv_.set_edge_attribute(edge, "tailport", "ne");
231  gv_.set_edge_attribute(edge, "headport", "se");
232  }
233  else {
234  gv_.set_edge_attribute(edge, "tailport", "e");
235  gv_.set_edge_attribute(edge, "headport", "e");
236  }
237  } // if
238  } // if
239  } // visit_type
240 
241  static void write_sorted(
242  std::map<control_points_enum, std::vector<node_type const *>> sorted,
243  graphviz & gv) {
244  std::vector<Agnode_t *> nodes;
245 
246  for(auto cp : sorted) {
247  for(auto n : cp.second) {
248  auto * node = gv.add_node(n->identifier().c_str(), n->label().c_str());
249  nodes.push_back(node);
250 
251  gv.set_node_attribute(node, "color", "black");
252  gv.set_node_attribute(node, "style", "filled");
253  gv.set_node_attribute(
254  node, "fillcolor", colors[static_cast<size_t>(cp.first) % 4]);
255  } // for
256  } // for
257 
258  for(size_t n{1}; n < nodes.size(); ++n) {
259  auto * edge = gv.add_edge(nodes[n - 1], nodes[n]);
260  gv.set_edge_attribute(edge, "penwidth", "1.5");
261  } // for
262  } // write_sorted
263 
264 private:
265  std::map<control_points_enum, dag> registry_;
266  graphviz & gv_;
267  int depth_;
268 
269 }; // struct point_writer
270 
271 #endif // FLECSI_ENABLE_GRAPHVIZ
272 
273 } // namespace ctrl_impl
274 } // namespace flecsi
Definition: graphviz.hh:91
Definition: point_walker.hh:52
std::string type()
Definition: demangle.hh:44
void visit_type()
Definition: point_walker.hh:135
Definition: point_walker.hh:115
Definition: point_walker.hh:82
size_t colors()
Definition: execution.hh:336
Definition: point_walker.hh:46
Definition: tuple_walker.hh:34
Definition: dag.hh:74
Definition: control.hh:31