Interface Documentation
Version: invalid
control.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 
21 #include "flecsi/execution.hh"
22 #include "flecsi/flog.hh"
23 #include "flecsi/util/constant.hh"
24 #include "flecsi/util/dag.hh"
25 #include "flecsi/util/demangle.hh"
26 
27 #include <functional>
28 #include <map>
29 #include <vector>
30 
31 namespace flecsi {
32 
33 inline log::devel_tag control_tag("control");
34 
35 #if defined(FLECSI_ENABLE_GRAPHVIZ)
36 inline program_option<bool> control_model_option("FleCSI Options",
37  "control-model",
38  "Output a dot file of the control model. This can be processed into a pdf "
39  "using the dot command, like:\n\033[0;36m$ dot -Tpdf input.dot > "
40  "output.pdf\033[0m",
41  {{flecsi::option_implicit, true}, {flecsi::option_zero}});
42 
43 inline program_option<bool> control_model_sorted_option("FleCSI Options",
44  "control-model-sorted",
45  "Output a dot file of the sorted control model actions.",
46  {{flecsi::option_implicit, true}, {flecsi::option_zero}});
47 #endif
48 
49 template<auto CP>
51 
55 template<bool (*Predicate)(), typename... ControlPoints>
57 
73 template<typename ControlPolicy>
74 struct control : ControlPolicy {
75 
76  using target_type = int (*)();
77 
78 private:
79  friend ControlPolicy;
80 
81  using control_points = typename ControlPolicy::control_points;
82  using control_points_enum = typename ControlPolicy::control_points_enum;
83  using node_policy = typename ControlPolicy::node_policy;
84 
86  friend point_walker;
87 
89  friend init_walker;
90 
91 #if defined(FLECSI_ENABLE_GRAPHVIZ)
92  using point_writer = ctrl_impl::point_writer<control<ControlPolicy>>;
93  friend point_writer;
94 #endif
95 
96  /*
97  Control node type. This just adds an executable target.
98  */
99 
100  struct control_node : node_policy {
101 
102  template<typename... Args>
103  control_node(target_type target, Args &&... args)
104  : node_policy(std::forward<Args>(args)...), target_(target) {}
105 
106  int execute() const {
107  return target_();
108  }
109 
110  private:
111  target_type target_;
112  }; // struct control_node
113 
114  /*
115  Use the ndoe type that is defined by the specialized DAG.
116  */
117 
118  using node_type = typename util::dag<control_node>::node_type;
119 
120  /*
121  Initialize the control point dags. This is necessary in order to
122  assign labels in the case that no actions are registered at one
123  or more control points.
124  */
125 
126  control() {
127  init_walker(registry_).template walk_types<control_points>();
128  }
129 
130  /*
131  The singleton instance is private, and should only be accessed by internal
132  types.
133  */
134 
135  static control & instance() {
136  static control c;
137  return c;
138  }
139 
140  /*
141  Return the dag at the given control point.
142  */
143 
144  util::dag<control_node> & control_point_dag(control_points_enum cp) {
145  registry_.try_emplace(cp, *cp);
146  return registry_[cp];
147  }
148 
149  /*
150  Return a map of the sorted dags under each control point.
151  */
152 
153  std::map<control_points_enum, std::vector<node_type const *>> sort() {
154  std::map<control_points_enum, std::vector<node_type const *>> sorted;
155  for(auto & d : registry_) {
156  sorted.try_emplace(d.first, d.second.sort());
157  }
158  return sorted;
159  }
160 
161  /*
162  Run the control model.
163  */
164 
165  int run() {
166  int status{flecsi::run::status::success};
167  point_walker(sort(), status).template walk_types<control_points>();
168  return status;
169  } // run
170 
171  /*
172  Output a graph of the control model.
173  */
174 
175 #if defined(FLECSI_ENABLE_GRAPHVIZ)
176  int write() {
178  point_writer(registry_, gv).template walk_types<control_points>();
179  std::string file = program() + "-control-model.dot";
180  gv.write(file);
181  return flecsi::run::status::control;
182  } // write
183 
184  int write_sorted() {
186  point_writer::write_sorted(sort(), gv);
187  std::string file = program() + "-control-model-sorted.dot";
188  gv.write(file);
189  return flecsi::run::status::control;
190  } // write_sorted
191 #endif
192 
193  std::map<control_points_enum, util::dag<control_node>> registry_;
194 
195 public:
205  template<target_type Target, control_points_enum ControlPoint>
206  struct action {
207 
208  template<target_type U, control_points_enum V>
209  friend struct action;
210 
221  template<typename... Args>
222  action(Args &&... args)
223  : node_(util::symbol<*Target>(), Target, std::forward<Args>(args)...) {
224  instance().control_point_dag(ControlPoint).push_back(&node_);
225  }
226 
227  /*
228  Dummy type used to force namespace scope execution.
229  */
230 
231  struct dependency {};
232 
243  template<target_type U, control_points_enum V>
244  dependency add(action<U, V> const & from) {
245  static_assert(ControlPoint == V,
246  "you cannot add dependencies between actions under different control "
247  "points");
248  node_.push_back(&from.node_);
249  return {};
250  }
251 
255  template<target_type F>
256  void push_back(action<F, ControlPoint> const & from) {
257  node_.push_back(&from.node_);
258  }
259 
260  private:
261  node_type node_;
262  }; // struct action
263 
270  static int execute() {
271  return instance().run();
272  } // execute
273 
278  static int check_options() {
279  int retval{flecsi::run::status::success};
280 #if defined(FLECSI_ENABLE_GRAPHVIZ)
281  if(control_model_option.has_value()) {
282  retval |= instance().write();
283  } // if
284  if(control_model_sorted_option.has_value()) {
285  retval |= instance().write_sorted();
286  } // if
287 #endif
288  return retval;
289  } // write
290 
291 }; // struct control
292 
293 } // namespace flecsi
action(Args &&... args)
Definition: control.hh:222
Definition: flog.hh:79
Definition: graphviz.hh:91
static int execute()
Definition: control.hh:270
Definition: control.hh:206
Definition: control.hh:231
dependency add(action< U, V > const &from)
Definition: control.hh:244
Definition: constant.hh:22
std::string const & program()
Definition: execution.hh:276
decltype(auto) execute(ARGS &&... args)
Definition: execution.hh:382
static int check_options()
Definition: control.hh:278
Definition: execution.hh:117
Definition: point_walker.hh:115
Definition: control.hh:74
Definition: point_walker.hh:82
Definition: dag.hh:43
Definition: point_walker.hh:46
Definition: control.hh:31