tt.h
Go to the documentation of this file.
1 #ifndef TTG_BASE_OP_H
2 #define TTG_BASE_OP_H
3 
4 #include <cstdint>
5 #include <iostream>
6 #include <optional>
7 #include <sstream>
8 #include <string>
9 #include <vector>
10 
11 #include "ttg/base/terminal.h"
12 #include "ttg/util/demangle.h"
13 
14 namespace ttg {
15 
16  namespace detail {
17  // If true prints trace of all assignments and all TT invocations
18  inline bool &tt_base_trace_accessor(void) {
19  static bool trace = false;
20  return trace;
21  }
22 
23  inline bool &op_base_lazy_pull_accessor(void) {
24  static bool lazy_pull = false;
25  return lazy_pull;
26  }
27  } // namespace detail
28 
30  class TTBase {
31  private:
32  int64_t instance_id;
33 
34  std::string name;
35  std::vector<TerminalBase *> inputs;
36  std::vector<TerminalBase *> outputs;
37  bool trace_instance = false;
38  const TTBase *owning_ttg = nullptr;
39  template <typename input_terminalsT, typename output_terminalsT>
40  friend class TTG; // TTG needs to be able to control owning_ttg
41 
42  bool executable = false;
43  bool is_ttg_ = false;
44  bool lazy_pull_instance = false;
45 
46  // Default copy/move/assign all OK
47  static uint64_t next_instance_id() {
48  static uint64_t id = 0;
49  return id++;
50  }
51 
52  protected:
53  void set_input(size_t i, TerminalBase *t) {
54  if (i >= inputs.size()) throw(name + ":TTBase: out of range i setting input");
55  inputs[i] = t;
56  }
57 
58  void set_output(size_t i, TerminalBase *t) {
59  if (i >= outputs.size()) throw(name + ":TTBase: out of range i setting output");
60  outputs[i] = t;
61  }
62 
63  template <bool out, typename terminalT, std::size_t i, typename setfuncT>
64  void register_terminal(terminalT &term, const std::string &name, const setfuncT setfunc) {
65  term.set(this, i, name, detail::demangled_type_name<typename terminalT::key_type>(),
66  detail::demangled_type_name<typename terminalT::value_type>(),
68  : (std::is_const_v<typename terminalT::value_type> ? TerminalBase::Type::Read
70  (this->*setfunc)(i, &term);
71  }
72 
73  template <bool out, std::size_t... IS, typename terminalsT, typename namesT, typename setfuncT>
74  void register_terminals(std::index_sequence<IS...>, terminalsT &terms, const namesT &names,
75  const setfuncT setfunc) {
76  int junk[] = {
77  0, (register_terminal<out, std::tuple_element_t<IS, terminalsT>, IS>(std::get<IS>(terms), names[IS], setfunc),
78  0)...};
79  junk[0]++;
80  }
81 
82  // Used by op ... terminalsT will be a tuple of terminals
83  template <typename terminalsT, typename namesT>
84  void register_input_terminals(terminalsT &terms, const namesT &names) {
85  register_terminals<false>(std::make_index_sequence<std::tuple_size_v<terminalsT>>{}, terms, names,
87  }
88 
89  // Used by op ... terminalsT will be a tuple of terminals
90  template <typename terminalsT, typename namesT>
91  void register_output_terminals(terminalsT &terms, const namesT &names) {
92  register_terminals<true>(std::make_index_sequence<std::tuple_size_v<terminalsT>>{}, terms, names,
94  }
95 
96  // Used by composite TT ... terminalsT will be a tuple of pointers to terminals
97  template <std::size_t... IS, typename terminalsT, typename setfuncT>
98  void set_terminals(std::index_sequence<IS...>, terminalsT &terms, const setfuncT setfunc) {
99  int junk[] = {0, ((this->*setfunc)(IS, std::get<IS>(terms)), 0)...};
100  junk[0]++;
101  }
102 
103  // Used by composite TT ... terminalsT will be a tuple of pointers to terminals
104  template <typename terminalsT, typename setfuncT>
105  void set_terminals(const terminalsT &terms, const setfuncT setfunc) {
106  set_terminals(std::make_index_sequence<std::tuple_size_v<terminalsT>>{}, terms, setfunc);
107  }
108 
109  private:
110  // non-copyable, but movable
111  TTBase(const TTBase &) = delete;
112  TTBase &operator=(const TTBase &) = delete;
113 
114  protected:
115  TTBase(TTBase &&other)
116  : instance_id(other.instance_id)
117  , is_ttg_(std::move(other.is_ttg_))
118  , name(std::move(other.name))
119  , inputs(std::move(other.inputs))
120  , outputs(std::move(other.outputs)) {
121  other.instance_id = -1;
122  }
123  TTBase &operator=(TTBase &&other) {
124  instance_id = other.instance_id;
125  is_ttg_ = std::move(other.is_ttg_);
126  name = std::move(other.name);
127  inputs = std::move(other.inputs);
128  outputs = std::move(other.outputs);
129  other.instance_id = -1;
130  return *this;
131  }
132 
133  TTBase(const std::string &name, size_t numins, size_t numouts)
134  : instance_id(next_instance_id()), is_ttg_(false), name(name), inputs(numins), outputs(numouts) {}
135 
136  static const std::vector<TerminalBase *> *&outputs_tls_ptr_accessor() {
137  static thread_local const std::vector<TerminalBase *> *outputs_tls_ptr = nullptr;
138  return outputs_tls_ptr;
139  }
140  void set_outputs_tls_ptr() { outputs_tls_ptr_accessor() = &this->outputs; }
141  void set_outputs_tls_ptr(const std::vector<TerminalBase *> *ptr) { outputs_tls_ptr_accessor() = ptr; }
142 
143  public:
144  virtual ~TTBase() = default;
145 
149  virtual void invoke() {
150  std::cerr << "TTBase::invoke() invoked on a TT that did not override it" << std::endl;
151  ttg::abort();
152  }
153 
156  static bool set_trace_all(bool value) {
157  if constexpr (trace_enabled()) std::swap(ttg::detail::tt_base_trace_accessor(), value);
158  return value;
159  }
160 
161  //Sets lazy pulling on.
162  //Lazy pulling delays invoking pull terminals until all inputs from push terminals for a task have arrived.
163  //Default is false.
164  static bool set_lazy_pull(bool value) {
165  std::swap(ttg::detail::op_base_lazy_pull_accessor(), value);
166  return value;
167  }
168 
171  bool set_trace_instance(bool value) {
172  if constexpr (trace_enabled()) std::swap(trace_instance, value);
173  return value;
174  }
175 
177  bool tracing() const {
178  if constexpr (trace_enabled())
179  return ttg::detail::tt_base_trace_accessor() || trace_instance;
180  else
181  return false;
182  }
183 
185  template <typename T, typename... Ts>
186  inline void trace(const T &t, const Ts &...ts) {
187  if constexpr (trace_enabled()) {
188  if (this->tracing()) {
189  log(t, ts...);
190  }
191  }
192  }
193 
194  bool set_lazy_pull_instance(bool value) {
195  std::swap(lazy_pull_instance, value);
196  return value;
197  }
198 
199  bool is_lazy_pull() { return ttg::detail::op_base_lazy_pull_accessor() || lazy_pull_instance; }
200 
201  std::optional<std::reference_wrapper<const TTBase>> ttg() const {
202  return owning_ttg ? std::cref(*owning_ttg) : std::optional<std::reference_wrapper<const TTBase>>{};
203  }
204 
205  const TTBase *ttg_ptr() const {
206  return owning_ttg;
207  }
208 
209  bool is_ttg() const {
210  return is_ttg_;
211  }
212 
214  void set_name(const std::string &name) { this->name = name; }
215 
217  const std::string &get_name() const { return name; }
218 
220  std::string get_class_name() const { return ttg::detail::demangled_type_name(this); }
221 
223  const std::vector<TerminalBase *> &get_inputs() const { return inputs; }
224 
226  const std::vector<TerminalBase *> &get_outputs() const { return outputs; }
227 
229  static const std::vector<TerminalBase *> *get_outputs_tls_ptr() { return outputs_tls_ptr_accessor(); }
230 
232  virtual ttg::World get_world() const = 0;
233 
235  ttg::TerminalBase *in(size_t i) {
236  if (i >= inputs.size()) throw name + ":TTBase: you are requesting an input terminal that does not exist";
237  return inputs[i];
238  }
239 
241  ttg::TerminalBase *out(size_t i) {
242  if (i >= outputs.size()) throw name + "TTBase: you are requesting an output terminal that does not exist";
243  return outputs[i];
244  }
245 
247  template <std::size_t i>
249  return in(i);
250  }
251 
253  template <std::size_t i>
255  return out(i);
256  }
257 
258  auto get_instance_id() const { return instance_id; }
259 
262  virtual void fence() = 0;
263 
264  virtual void release() {}
265 
267  virtual void make_executable() = 0;
268 
271  bool is_executable() const { return executable; }
272 
276 #define TTG_OP_ASSERT_EXECUTABLE() \
277  do { \
278  if (!this->is_executable()) { \
279  std::ostringstream oss; \
280  oss << "TT is not executable at " << __FILE__ << ":" << __LINE__; \
281  throw std::logic_error(oss.str().c_str()); \
282  } \
283  } while (0);
284  };
285 
286  inline void TTBase::make_executable() { executable = true; }
287 
288 } // namespace ttg
289 
290 #endif // TTG_BASE_OP_H
A base class for all template tasks.
Definition: tt.h:30
const std::vector< TerminalBase * > & get_inputs() const
Returns the vector of input terminals.
Definition: tt.h:223
void set_terminals(const terminalsT &terms, const setfuncT setfunc)
Definition: tt.h:105
virtual void invoke()
Definition: tt.h:149
void set_outputs_tls_ptr(const std::vector< TerminalBase * > *ptr)
Definition: tt.h:141
virtual ~TTBase()=default
const std::vector< TerminalBase * > & get_outputs() const
Returns the vector of output terminals.
Definition: tt.h:226
void trace(const T &t, const Ts &...ts)
Like ttg::trace(), but only produces tracing output if this->tracing()==true
Definition: tt.h:186
ttg::TerminalBase * in(size_t i)
Returns a pointer to the i'th input terminal.
Definition: tt.h:235
TTBase(const std::string &name, size_t numins, size_t numouts)
Definition: tt.h:133
static const std::vector< TerminalBase * > * get_outputs_tls_ptr()
Returns this thread's pointer to the vector of output terminals.
Definition: tt.h:229
auto get_instance_id() const
Definition: tt.h:258
void register_terminal(terminalT &term, const std::string &name, const setfuncT setfunc)
Definition: tt.h:64
ttg::TerminalBase * in()
Returns a pointer to the i'th input terminal ... to make API consistent with TT.
Definition: tt.h:248
void set_terminals(std::index_sequence< IS... >, terminalsT &terms, const setfuncT setfunc)
Definition: tt.h:98
bool set_trace_instance(bool value)
Definition: tt.h:171
std::optional< std::reference_wrapper< const TTBase > > ttg() const
Definition: tt.h:201
virtual void make_executable()=0
Marks this executable.
Definition: tt.h:286
bool tracing() const
Definition: tt.h:177
virtual ttg::World get_world() const =0
std::string get_class_name() const
Gets the demangled class name (uses RTTI)
Definition: tt.h:220
bool set_lazy_pull_instance(bool value)
Definition: tt.h:194
bool is_executable() const
Definition: tt.h:271
static const std::vector< TerminalBase * > *& outputs_tls_ptr_accessor()
Definition: tt.h:136
void set_output(size_t i, TerminalBase *t)
Definition: tt.h:58
void set_name(const std::string &name)
Sets the name of this operation.
Definition: tt.h:214
const std::string & get_name() const
Gets the name of this operation.
Definition: tt.h:217
static bool set_lazy_pull(bool value)
Definition: tt.h:164
TTBase & operator=(TTBase &&other)
Definition: tt.h:123
bool is_ttg() const
Definition: tt.h:209
virtual void release()
Definition: tt.h:264
TTBase(TTBase &&other)
Definition: tt.h:115
static bool set_trace_all(bool value)
Definition: tt.h:156
void register_input_terminals(terminalsT &terms, const namesT &names)
Definition: tt.h:84
void register_terminals(std::index_sequence< IS... >, terminalsT &terms, const namesT &names, const setfuncT setfunc)
Definition: tt.h:74
ttg::TerminalBase * out(size_t i)
Returns a pointer to the i'th output terminal.
Definition: tt.h:241
bool is_lazy_pull()
Definition: tt.h:199
virtual void fence()=0
const TTBase * ttg_ptr() const
Definition: tt.h:205
ttg::TerminalBase * out()
Returns a pointer to the i'th output terminal ... to make API consistent with TT.
Definition: tt.h:254
void set_input(size_t i, TerminalBase *t)
Definition: tt.h:53
void register_output_terminals(terminalsT &terms, const namesT &names)
Definition: tt.h:91
void set_outputs_tls_ptr()
Definition: tt.h:140
a template task graph implementation
Definition: tt.h:31
@ Write
can only be written to
@ Read
can only be used to read immutable data
@ Consume
can only be used to read consumable data
typename make_index_sequence_t< I... >::type make_index_sequence
bool & op_base_lazy_pull_accessor(void)
Definition: tt.h:23
bool & tt_base_trace_accessor(void)
Definition: tt.h:18
top-level TTG namespace contains runtime-neutral functionality
Definition: keymap.h:8
void abort()
Aborts the TTG program using the default backend's ttg_abort method.
Definition: run.h:62
void log(const T &t, const Ts &... ts)
atomically prints to std::clog a sequence of items (separated by ttg::print_separator) followed by st...
Definition: print.h:146
void trace(const T &t, const Ts &... ts)
Definition: trace.h:43
constexpr bool trace_enabled()
returns whether tracing was enabled at configure time
Definition: trace.h:15