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