ttg 1.0.0
Template Task Graph (TTG): flowgraph-based programming model for high-performance distributed-memory algorithms
Loading...
Searching...
No Matches
terminal.h
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2#ifndef TTG_TERMINALS_H
3#define TTG_TERMINALS_H
4
5#include <exception>
6#include <stdexcept>
7#include <type_traits>
8
9#include "ttg/base/terminal.h"
10#include "ttg/fwd.h"
11#include "ttg/util/demangle.h"
12#include "ttg/util/meta.h"
13#include "ttg/util/trace.h"
14#include "ttg/world.h"
15#include "ttg/run.h"
16
17namespace ttg {
18 namespace detail {
19
20 /* Wraps any key,value data structure.
21 * Elements of the data structure can be accessed using get method, which calls the at method of the Container.
22 * keyT - taskID
23 * valueT - Value type of the Container
24 */
25 template<typename keyT, typename valueT>
27 std::function<valueT (keyT const& key)> get = nullptr;
28 std::function<size_t (keyT const& key)> owner = nullptr;
29
30 ContainerWrapper() = default;
34
35 template<typename T, typename mapperT, typename keymapT, std::enable_if_t<!std::is_same<std::decay_t<T>,
36 ContainerWrapper>{}, bool> = true>
37 //Store a pointer to the user's container in std::any, no copies
39 keymapT &&keymap) : get([&t, mapper = std::forward<mapperT>(mapper)](keyT const &key) {
40 if constexpr (!std::is_class_v<T> && std::is_invocable_v<T, keyT>) {
41 auto k = mapper(key);
42 return t(k); //Call the user-defined lambda function.
43 }
44 else
45 {
46 auto k = mapper(key);
47 //at method returns a const ref to the item.
48 return t.at(k);
49 }
50 }),
51 owner([&t, mapper = std::forward<mapperT>(mapper),
52 keymap = std::forward<keymapT>(keymap)](keyT const &key) {
53 auto idx = mapper(key); //Mapper to map task ID to index of the data structure.
54 return keymap(idx);
55 })
56 {}
57 };
58
59 template <typename valueT> struct ContainerWrapper<void, valueT> {
60 std::function<valueT ()> get = nullptr;
61 std::function<size_t ()> owner = nullptr;
62 };
63
64 template <typename keyT> struct ContainerWrapper<keyT, void> {
65 std::function<std::nullptr_t (keyT const& key)> get = nullptr;
66 std::function<size_t (keyT const& key)> owner = nullptr;
67 };
68
69 template <typename valueT> struct ContainerWrapper<ttg::Void, valueT> {
70 std::function<valueT ()> get = nullptr;
71 std::function<size_t ()> owner = nullptr;
72 };
73
74 template <> struct ContainerWrapper<void, void> {
75 std::function<std::nullptr_t ()> get = nullptr;
76 std::function<size_t ()> owner = nullptr;
77 };
78 } //namespace detail
79
82 template <typename keyT = void>
84 public:
85 typedef keyT key_type;
86 static_assert(std::is_same_v<keyT, std::decay_t<keyT>>,
87 "InTerminalBase<keyT,valueT> assumes keyT is a non-decayable type");
88 using setsize_callback_type = meta::detail::setsize_callback_t<keyT>;
89 using finalize_callback_type = meta::detail::finalize_callback_t<keyT>;
90 static constexpr bool is_an_input_terminal = true;
91
92 protected:
94
97
103
104 private:
105 // No moving, copying, assigning permitted
106 InTerminalBase(InTerminalBase &&other) = delete;
107 InTerminalBase(const InTerminalBase &other) = delete;
108 InTerminalBase &operator=(const InTerminalBase &other) = delete;
109 InTerminalBase &operator=(const InTerminalBase &&other) = delete;
110
111 public:
112 template <typename Key = keyT>
113 std::enable_if_t<!meta::is_void_v<Key>, void> set_size(const Key &key, std::size_t size) {
114 if (!setsize_callback) throw std::runtime_error("set_size callback not initialized");
116 }
117
118 template <typename Key = keyT>
119 std::enable_if_t<meta::is_void_v<Key>, void> set_size(std::size_t size) {
120 if (!setsize_callback) throw std::runtime_error("set_size callback not initialized");
122 }
123
124 template <typename Key = keyT>
125 std::enable_if_t<!meta::is_void_v<Key>, void> finalize(const Key &key) {
126 // std::cout << "In::finalize::\n";
127 if (!finalize_callback) throw std::runtime_error("finalize callback not initialized");
129 }
130
131 template <typename Key = keyT>
132 std::enable_if_t<meta::is_void_v<Key>, void> finalize() {
133 if (!finalize_callback) throw std::runtime_error("finalize callback not initialized");
135 }
136 };
137
142
143 template <typename keyT = void, typename valueT = void>
144 class In : public InTerminalBase<keyT> {
145 public:
147 typedef valueT value_type;
148 typedef keyT key_type;
149 static_assert(std::is_same_v<keyT, std::decay_t<keyT>>, "In<keyT,valueT> assumes keyT is a non-decayable type");
150 // valueT can be T or const T
151 static_assert(std::is_same_v<std::remove_const_t<valueT>, std::decay_t<valueT>>,
152 "In<keyT,valueT> assumes std::remove_const<T> is a non-decayable type");
154 using send_callback_type = meta::detail::send_callback_t<keyT, std::decay_t<valueT>>;
155 using move_callback_type = meta::detail::move_callback_t<keyT, std::decay_t<valueT>>;
156 using broadcast_callback_type = meta::detail::broadcast_callback_t<keyT, std::decay_t<valueT>>;
159 using prepare_send_callback_type = meta::detail::prepare_send_callback_t<keyT, std::decay_t<valueT>>;
160 static constexpr bool is_an_input_terminal = true;
162
163 private:
164 send_callback_type send_callback;
165 move_callback_type move_callback;
166 broadcast_callback_type broadcast_callback;
167 prepare_send_callback_type prepare_send_callback;
168
169 // No moving, copying, assigning permitted
170 In(In &&other) = delete;
171 In(const In &other) = delete;
172 In &operator=(const In &other) = delete;
173 In &operator=(const In &&other) = delete;
174
175 void connect(TerminalBase *p) override {
176 throw "Edge: to connect terminals use out->connect(in) rather than in->connect(out)";
177 }
178
179 public:
181 In() : InTerminalBase<keyT>(std::is_const_v<valueT> ? TerminalBase::Type::Read : TerminalBase::Type::Consume){};
182
193 void set_callback(const send_callback_type &send_callback, const move_callback_type &move_callback,
194 const broadcast_callback_type &bcast_callback = broadcast_callback_type{},
197 const prepare_send_callback_type &prepare_send_callback = prepare_send_callback_type{}) {
198 this->send_callback = send_callback;
199 this->move_callback = move_callback;
200 this->broadcast_callback = bcast_callback;
201 this->prepare_send_callback = prepare_send_callback;
203 }
204
205 template <typename Key = keyT, typename Value = valueT>
206 std::enable_if_t<meta::is_none_void_v<Key, Value>, void>
207 send(const Key &key, Value &&value) {
208 static_assert(meta::is_none_void_v<keyT, valueT>, "ttg::send<>() sending to a terminal expecting void key and value; use ttg::send<>() instead");
209 static_assert(!meta::is_void_v<keyT>, "ttg::send<>(key,value) sending to a terminal expecting void key; use ttg::sendv(value) instead");
210 static_assert(!meta::is_void_v<valueT>, "ttg::send<>(key,value) sending to a terminal expecting void value; use ttg::sendk(key) instead");
211 constexpr auto value_is_rvref = !std::is_reference_v<Value>;
212 if constexpr (value_is_rvref) {
213 if (!move_callback) throw std::runtime_error("move callback not initialized");
214 move_callback(key, std::move(value));
215 } else {
216 if (!send_callback) throw std::runtime_error("send callback not initialized");
217 send_callback(key, value);
218 }
219 }
220
221 template <typename Key = keyT>
222 std::enable_if_t<!meta::is_void_v<Key>, void> sendk(const Key &key) {
223 static_assert(!meta::is_void_v<keyT> && meta::is_void_v<valueT>, "ttg::sendk<>(key) sending to a terminal expecting void key and nonvoid value; use ttg::sendv<>(value) instead");
224 static_assert(!meta::is_void_v<keyT>, "ttg::sendk<>(key) sending to a terminal expecting void key; use ttg::send() instead");
225 static_assert(meta::is_void_v<valueT>, "ttg::sendk<>(key) sending to a terminal expecting nonvoid value; use ttg::send(key,value) instead");
226 if (!send_callback) throw std::runtime_error("send callback not initialized");
227 send_callback(key);
228 }
229
230 template <typename Value = valueT>
231 std::enable_if_t<!meta::is_void_v<Value>, void> sendv(
232 Value &&value) {
233 static_assert(meta::is_void_v<keyT> && !meta::is_void_v<valueT>, "ttg::sendv<>(value) sending to a terminal expecting nonvoid key and void value; use ttg::sendk<>(key) instead");
234 static_assert(meta::is_void_v<keyT>, "ttg::sendv<>(value) sending to a terminal expecting nonvoid key; use ttg::send(key, value) instead");
235 static_assert(!meta::is_void_v<valueT>, "ttg::sendv<>(value) sending to a terminal expecting void value; use ttg::send() instead");
236 constexpr auto value_is_rvref = !std::is_reference_v<Value>;
237 if constexpr (value_is_rvref) {
238 if (!move_callback) throw std::runtime_error("move callback not initialized");
239 move_callback(std::move(value));
240 }
241 else {
242 if (!send_callback) throw std::runtime_error("send callback not initialized");
243 send_callback(value);
244 }
245 }
246
247 void send() {
248 static_assert(!meta::is_none_void_v<keyT, valueT>, "ttg::send<>() sending to a terminal expecting nonvoid key and value; use ttg::send<>(key,value) instead");
249 static_assert(meta::is_void_v<keyT>, "ttg::send<>() sending to a terminal expecting nonvoid key; use ttg::sendk<>(key) instead");
250 static_assert(meta::is_void_v<valueT>, "ttg::send<>() sending to a terminal expecting nonvoid value; use ttg::sendv<>(value) instead");
251 if (!send_callback) throw std::runtime_error("send callback not initialized");
252 send_callback();
253 }
254
255 // An optimized implementation will need a separate callback for broadcast
256 // with a specific value for rangeT
257 template <typename rangeT, typename Value>
258 std::enable_if_t<!meta::is_void_v<Value>, void> broadcast(const rangeT &keylist, const Value &value) {
259 if (broadcast_callback) {
260 if constexpr (ttg::meta::is_iterable_v<rangeT>) {
261 broadcast_callback(ttg::span<const keyT>(&(*std::begin(keylist)), std::distance(std::begin(keylist), std::end(keylist))),
262 value);
263 } else {
264 /* got something we cannot iterate over (single element?) so put one element in the span */
265 broadcast_callback(ttg::span<const keyT>(&keylist, 1), value);
266 }
267 } else {
268 if constexpr (ttg::meta::is_iterable_v<rangeT>) {
269 for (auto &&key : keylist) send(key, value);
270 } else {
271 /* single element */
272 send(keylist, value);
273 }
274 }
275 }
276
277 template <typename rangeT, typename Value>
278 std::enable_if_t<!meta::is_void_v<Value>, void> broadcast(const rangeT &keylist, Value &&value) {
279 const Value &v = value;
280 if (broadcast_callback) {
281 if constexpr (ttg::meta::is_iterable_v<rangeT>) {
282 broadcast_callback(
283 ttg::span<const keyT>(&(*std::begin(keylist)), std::distance(std::begin(keylist), std::end(keylist))), v);
284 } else {
285 /* got something we cannot iterate over (single element?) so put one element in the span */
286 broadcast_callback(ttg::span<const keyT>(&keylist, 1), v);
287 }
288 } else {
289 if constexpr (ttg::meta::is_iterable_v<rangeT>) {
290 for (auto &&key : keylist) send(key, v);
291 } else {
292 /* got something we cannot iterate over (single element?) so put one element in the span */
293 send(ttg::span<const keyT>(&keylist, 1), v);
294 }
295 }
296 }
297
298 template <typename rangeT, typename Value = valueT>
299 std::enable_if_t<meta::is_void_v<Value>, void> broadcast(const rangeT &keylist) {
300 if (broadcast_callback) {
301 if constexpr (ttg::meta::is_iterable_v<rangeT>) {
302 broadcast_callback(
303 ttg::span<const keyT>(&(*std::begin(keylist)), std::distance(std::begin(keylist), std::end(keylist))));
304 } else {
305 /* got something we cannot iterate over (single element?) so put one element in the span */
306 broadcast_callback(ttg::span<const keyT>(&keylist, 1));
307 }
308 } else {
309 if constexpr (ttg::meta::is_iterable_v<rangeT>) {
310 for (auto &&key : keylist) sendk(key);
311 } else {
312 /* got something we cannot iterate over (single element?) so put one element in the span */
313 sendk(ttg::span<const keyT>(&keylist, 1));
314 }
315 }
316 }
317
318
319 template <typename rangeT, typename Value>
320 void prepare_send(const rangeT &keylist, Value &&value) {
321 const std::remove_reference_t<Value> &v = value;
322 if (prepare_send_callback) {
323 if constexpr (ttg::meta::is_iterable_v<rangeT>) {
324 prepare_send_callback(ttg::span<const keyT>(&(*std::begin(keylist)),
325 std::distance(std::begin(keylist), std::end(keylist))),
326 v);
327 } else {
328 /* got something we cannot iterate over (single element?) so put one element in the span */
329 prepare_send_callback(ttg::span<const keyT>(&keylist, 1), v);
330 }
331 }
332 }
333
334 template <typename Value>
335 void prepare_send(Value &&value) {
336 const std::remove_reference_t<Value> &v = value;
337 if (prepare_send_callback) {
338 prepare_send_callback(v);
339 }
340 }
341 };
342
343 namespace detail {
344 template <typename keyT, typename... valuesT>
346 using type = std::tuple<ttg::In<keyT, valuesT>...>;
347 };
348
349 template <typename keyT, typename... valuesT>
350 struct input_terminals_tuple<keyT, std::tuple<valuesT...>> {
351 using type = std::tuple<ttg::In<keyT, valuesT>...>;
352 };
353
354 template <typename keyT, typename... valuesT>
355 using input_terminals_tuple_t = typename input_terminals_tuple<keyT, valuesT...>::type;
356 } // namespace detail
357
358 namespace meta {
360 template <typename T>
361 inline constexpr bool is_input_terminal_v = false;
362 template <typename keyT>
363 inline constexpr bool is_input_terminal_v<InTerminalBase<keyT>> = true;
364 template <typename keyT, typename valueT>
365 inline constexpr bool is_input_terminal_v<In<keyT, valueT>> = true;
366
367 template <typename T>
368 struct is_input_terminal : std::bool_constant<is_input_terminal_v<T>> {};
369 } // namespace meta
370
373 template <typename keyT = void>
375 public:
376 using key_type = keyT;
377 static_assert(std::is_same_v<keyT, std::decay_t<keyT>>, "Out<keyT,valueT> assumes keyT is a non-decayable type");
378 static constexpr bool is_an_output_terminal = true;
379
380 private:
381 // No moving, copying, assigning permitted
382 OutTerminalBase(OutTerminalBase &&other) = delete;
383 OutTerminalBase(const OutTerminalBase &other) = delete;
384 OutTerminalBase &operator=(const OutTerminalBase &other) = delete;
385 OutTerminalBase &operator=(const OutTerminalBase &&other) = delete;
386
387 public:
389
390 auto nsuccessors() const { return get_connections().size(); }
391 const auto &successors() const { return get_connections(); }
392
393 template <typename Key = keyT>
394 std::enable_if_t<!meta::is_void_v<Key>, void> set_size(const Key &key, std::size_t size) {
395 for (auto &&successor : successors()) {
396 assert(successor->get_type() != TerminalBase::Type::Write);
397 static_cast<InTerminalBase<keyT> *>(successor)->set_size(key, size);
398 }
399 }
400
401 template <typename Key = keyT>
402 std::enable_if_t<meta::is_void_v<Key>, void> set_size(std::size_t size) {
403 for (auto &&successor : successors()) {
404 assert(successor->get_type() != TerminalBase::Type::Write);
405 static_cast<InTerminalBase<keyT> *>(successor)->set_size(size);
406 }
407 }
408
409 template <typename Key = keyT>
410 std::enable_if_t<!meta::is_void_v<Key>, void> finalize(const Key &key) {
411 for (auto &&successor : successors()) {
412 assert(successor->get_type() != TerminalBase::Type::Write);
413 static_cast<InTerminalBase<keyT> *>(successor)->finalize(key);
414 }
415 }
416
417 template <typename Key = keyT>
418 std::enable_if_t<meta::is_void_v<Key>, void> finalize() {
419 for (auto successor : successors()) {
420 assert(successor->get_type() != TerminalBase::Type::Write);
421 static_cast<InTerminalBase<keyT> *>(successor)->finalize();
422 }
423 }
424 };
425
429 template <typename keyT = void, typename valueT = void>
430 class Out : public OutTerminalBase<keyT> {
431 public:
432 using value_type = valueT;
434 static_assert(std::is_same_v<valueT, std::decay_t<valueT>>,
435 "Out<keyT,valueT> assumes valueT is a non-decayable type");
437 static constexpr bool is_an_output_terminal = true;
438
439 private:
440 // No moving, copying, assigning permitted
441 Out(Out &&other) = delete;
442 Out(const Out &other) = delete;
443 Out &operator=(const Out &other) = delete;
444 Out &operator=(const Out &&other) = delete;
445
446 public:
447 Out() = default;
448
450 void connect(TerminalBase *in) override {
451#ifndef NDEBUG
452 if (in->get_type() == TerminalBase::Type::Read) {
453 typedef In<keyT, std::add_const_t<valueT>> input_terminal_type;
454 if (!dynamic_cast<input_terminal_type *>(in))
455 throw std::invalid_argument(
456 std::string("you are trying to connect terminals with incompatible types:\ntype of this Terminal = ") +
457 detail::demangled_type_name(this) + "\ntype of other Terminal" + detail::demangled_type_name(in));
458 } else if (in->get_type() == TerminalBase::Type::Consume) {
459 typedef In<keyT, valueT> input_terminal_type;
460 if (!dynamic_cast<input_terminal_type *>(in))
461 throw std::invalid_argument(
462 std::string("you are trying to connect terminals with incompatible types:\ntype of this Terminal = ") +
463 detail::demangled_type_name(this) + "\ntype of other Terminal" + detail::demangled_type_name(in));
464 } else // successor->type() == TerminalBase::Type::Write
465 throw std::invalid_argument(std::string("you are trying to connect an Out terminal to another Out terminal"));
466 trace(rank(), ": connected Out<> ", this->get_name(), "(ptr=", this, ") to In<> ", in->get_name(), "(ptr=", in,
467 ")");
468#endif
469 this->connect_base(in);
470 //If I am a pull terminal, add me as (in)'s predecessor
471 if (this->is_pull_terminal)
472 in->connect_pull(this);
473 }
474
475 template <typename Key = keyT, typename Value = valueT>
476 std::enable_if_t<!meta::is_void_v<Key> && meta::is_void_v<Value>, void> sendk(const Key &key) {
477 for (auto &&successor : this->successors()) {
478 assert(successor->get_type() != TerminalBase::Type::Write);
479 if (successor->get_type() == TerminalBase::Type::Read) {
480 static_cast<In<keyT, std::add_const_t<valueT>> *>(successor)->sendk(key);
481 } else if (successor->get_type() == TerminalBase::Type::Consume) {
482 static_cast<In<keyT, valueT> *>(successor)->sendk(key);
483 }
484 }
485 }
486
487 template <typename Key = keyT, typename Value = valueT>
488 std::enable_if_t<meta::is_void_v<Key> && !meta::is_void_v<Value>, void> sendv(Value&& value) {
489 const std::size_t N = this->nsuccessors();
490 TerminalBase *move_successor = nullptr;
491 // send copies to every terminal except the one we will move the results to
492 for (std::size_t i = 0; i != N; ++i) {
493 TerminalBase *successor = this->successors().at(i);
494 if (successor->get_type() == TerminalBase::Type::Read) {
495 // if only have 1 successor forward value even if successor is read-only, so we can deal with move-only types
496 auto* read_successor = static_cast<In<keyT, std::add_const_t<valueT>> *>(successor);
497 if (N != 1)
498 read_successor->sendv(value);
499 else
500 read_successor->sendv(std::forward<Value>(value));
501 } else if (successor->get_type() == TerminalBase::Type::Consume) {
502 if (nullptr == move_successor) {
503 move_successor = successor;
504 } else {
505 static_cast<In<keyT, valueT> *>(successor)->sendv(value);
506 }
507 }
508 }
509 if (nullptr != move_successor) {
510 static_cast<In<keyT, valueT> *>(move_successor)->sendv(std::forward<Value>(value));
511 }
512 }
513
514 template <typename Key = keyT, typename Value = valueT>
515 std::enable_if_t<meta::is_all_void_v<Key, Value>, void> send() {
516 trace(rank(), ": in ", this->get_name(), "(ptr=", this, ") Out<>::send: #successors=", this->successors().size());
517 for (auto &&successor : this->successors()) {
518 assert(successor->get_type() != TerminalBase::Type::Write);
519 if (successor->get_type() == TerminalBase::Type::Read) {
520 static_cast<In<keyT, std::add_const_t<valueT>> *>(successor)->send();
521 } else if (successor->get_type() == TerminalBase::Type::Consume) {
522 static_cast<In<keyT, valueT> *>(successor)->send();
523 } else {
524 throw std::logic_error("Out<>: invalid successor type");
525 }
526 trace("Out<> ", this->get_name(), "(ptr=", this, ") send to In<> ", successor->get_name(), "(ptr=", successor,
527 ")");
528 }
529 }
530
531 template <typename Key = keyT, typename Value = valueT>
532 std::enable_if_t<meta::is_none_void_v<Key, Value>, void>
533 send(const Key &key, Value &&value) {
534 const std::size_t N = this->nsuccessors();
535 TerminalBase *move_successor = nullptr;
536 // send copies to every terminal except the one we will move the results to
537 for (std::size_t i = 0; i != N; ++i) {
538 TerminalBase *successor = this->successors().at(i);
539 if (successor->get_type() == TerminalBase::Type::Read) {
540 // if only have 1 successor forward value even if successor is read-only, so we can deal with move-only types
541 auto* read_successor = static_cast<In<keyT, std::add_const_t<valueT>> *>(successor);
542 if (N != 1)
543 read_successor->send(key, value);
544 else
545 read_successor->send(key, std::forward<Value>(value));
546 } else if (successor->get_type() == TerminalBase::Type::Consume) {
547 if (nullptr == move_successor) {
548 move_successor = successor;
549 } else {
550 static_cast<In<keyT, valueT> *>(successor)->send(key, value);
551 }
552 }
553 }
554 if (nullptr != move_successor) {
555 static_cast<In<keyT, valueT> *>(move_successor)->send(key, std::forward<Value>(value));
556 }
557 }
558
559 // An optimized implementation will need a separate callback for broadcast
560 // with a specific value for rangeT
561 template <typename rangeT, typename Key = keyT, typename Value = valueT>
562 std::enable_if_t<meta::is_none_void_v<Key, Value>, void> broadcast(const rangeT &keylist,
563 const Value &value) { // NO MOVE YET
564 for (auto &&successor : this->successors()) {
565 assert(successor->get_type() != TerminalBase::Type::Write);
566 if (successor->get_type() == TerminalBase::Type::Read) {
567 static_cast<In<keyT, std::add_const_t<valueT>> *>(successor)->broadcast(keylist, value);
568 } else if (successor->get_type() == TerminalBase::Type::Consume) {
569 static_cast<In<keyT, valueT> *>(successor)->broadcast(keylist, value);
570 }
571 }
572 }
573
574 template <typename rangeT, typename Key = keyT>
575 std::enable_if_t<meta::is_none_void_v<Key> && meta::is_void_v<valueT>, void> broadcast(const rangeT &keylist) {
576 for (auto &&successor : this->successors()) {
577 assert(successor->get_type() != TerminalBase::Type::Write);
578 if (successor->get_type() == TerminalBase::Type::Read) {
579 static_cast<In<keyT, void> *>(successor)->broadcast(keylist);
580 } else if (successor->get_type() == TerminalBase::Type::Consume) {
581 static_cast<In<keyT, void> *>(successor)->broadcast(keylist);
582 }
583 }
584 }
585
586 template <typename rangeT, typename Key = keyT, typename Value = valueT>
587 std::enable_if_t<meta::is_none_void_v<Key> && !meta::is_void_v<valueT>, void>
588 prepare_send(const rangeT &keylist, const Value &value) {
589 for (auto &&successor : this->successors()) {
590 assert(successor->get_type() != TerminalBase::Type::Write);
591 if (successor->get_type() == TerminalBase::Type::Read) {
592 static_cast<In<keyT, std::add_const_t<valueT>> *>(successor)->prepare_send(keylist, value);
593 } else if (successor->get_type() == TerminalBase::Type::Consume) {
594 static_cast<In<keyT, valueT> *>(successor)->prepare_send(keylist, value);
595 }
596 }
597 }
598
599 template <typename Key = keyT, typename Value = valueT>
600 std::enable_if_t<meta::is_void_v<Key> && !meta::is_void_v<valueT>, void>
601 prepare_send(const Value &value) {
602 for (auto &&successor : this->successors()) {
603 assert(successor->get_type() != TerminalBase::Type::Write);
604 if (successor->get_type() == TerminalBase::Type::Read) {
605 static_cast<In<keyT, std::add_const_t<valueT>> *>(successor)->prepare_send(value);
606 } else if (successor->get_type() == TerminalBase::Type::Consume) {
607 static_cast<In<keyT, valueT> *>(successor)->prepare_send(value);
608 }
609 }
610 }
611 };
612
613 namespace meta {
615 template <typename T>
616 inline constexpr bool is_output_terminal_v = false;
617 template <typename keyT>
618 inline constexpr bool is_output_terminal_v<OutTerminalBase<keyT>> = true;
619 template <typename keyT, typename valueT>
620 inline constexpr bool is_output_terminal_v<Out<keyT, valueT>> = true;
621
622 template <typename T>
623 struct is_output_terminal : std::bool_constant<is_output_terminal_v<T>> {};
624
625 template <typename T>
626 struct is_output_terminal_tuple : std::false_type {};
627 template <typename... Ts>
628 struct is_output_terminal_tuple<std::tuple<Ts...>> : probe_all<is_output_terminal, Ts...> {};
629 template <typename... Ts>
630 inline constexpr bool is_output_terminal_tuple_v = is_output_terminal_tuple<Ts...>::value;
631
632 template <typename T>
634 template <typename T>
635 struct decays_to_output_terminal_tuple : std::bool_constant<decays_to_output_terminal_tuple_v<T>> {};
636
637 template <typename T>
639 is_output_terminal_tuple_v<std::decay_t<T>> &&std::is_lvalue_reference_v<T> &&
640 !std::is_const_v<std::remove_reference_t<T>>;
641 template <typename T>
643 : std::bool_constant<is_nonconst_lvalue_reference_to_output_terminal_tuple_v<T>> {};
644 } // namespace meta
645
646} // namespace ttg
647
648#endif // TTG_TERMINALS_H
Edge is used to connect In and Out terminals.
Definition edge.h:26
typename base_type::finalize_callback_type finalize_callback_type
Definition terminal.h:158
typename base_type::setsize_callback_type setsize_callback_type
Definition terminal.h:157
std::enable_if_t<!meta::is_void_v< Key >, void > sendk(const Key &key)
Definition terminal.h:222
void set_callback(const send_callback_type &send_callback, const move_callback_type &move_callback, const broadcast_callback_type &bcast_callback=broadcast_callback_type{}, const setsize_callback_type &setsize_callback=setsize_callback_type{}, const finalize_callback_type &finalize_callback=finalize_callback_type{}, const prepare_send_callback_type &prepare_send_callback=prepare_send_callback_type{})
Definition terminal.h:193
In()
Default constructor of an Input Terminal.
Definition terminal.h:181
static constexpr bool is_an_input_terminal
Definition terminal.h:160
void prepare_send(const rangeT &keylist, Value &&value)
Definition terminal.h:320
ttg::detail::ContainerWrapper< keyT, valueT > container
Definition terminal.h:161
valueT value_type
Definition terminal.h:147
std::enable_if_t< meta::is_void_v< Value >, void > broadcast(const rangeT &keylist)
Definition terminal.h:299
void send()
Definition terminal.h:247
std::enable_if_t< meta::is_none_void_v< Key, Value >, void > send(const Key &key, Value &&value)
Definition terminal.h:207
keyT key_type
Definition terminal.h:148
std::enable_if_t<!meta::is_void_v< Value >, void > broadcast(const rangeT &keylist, const Value &value)
Definition terminal.h:258
std::enable_if_t<!meta::is_void_v< Value >, void > sendv(Value &&value)
Definition terminal.h:231
meta::detail::send_callback_t< keyT, std::decay_t< valueT > > send_callback_type
Definition terminal.h:154
std::enable_if_t<!meta::is_void_v< Value >, void > broadcast(const rangeT &keylist, Value &&value)
Definition terminal.h:278
meta::detail::broadcast_callback_t< keyT, std::decay_t< valueT > > broadcast_callback_type
Definition terminal.h:156
meta::detail::prepare_send_callback_t< keyT, std::decay_t< valueT > > prepare_send_callback_type
Definition terminal.h:159
meta::detail::move_callback_t< keyT, std::decay_t< valueT > > move_callback_type
Definition terminal.h:155
void prepare_send(Value &&value)
Definition terminal.h:335
Base type for input terminals receiving messages annotated by task IDs of type keyT
Definition terminal.h:83
std::enable_if_t< meta::is_void_v< Key >, void > finalize()
Definition terminal.h:132
InTerminalBase(TerminalBase::Type t)
Definition terminal.h:93
finalize_callback_type finalize_callback
Definition terminal.h:96
setsize_callback_type setsize_callback
Definition terminal.h:95
std::enable_if_t<!meta::is_void_v< Key >, void > finalize(const Key &key)
Definition terminal.h:125
void set_callback(const setsize_callback_type &setsize_callback=setsize_callback_type{}, const finalize_callback_type &finalize_callback=finalize_callback_type{})
Definition terminal.h:98
meta::detail::setsize_callback_t< keyT > setsize_callback_type
Definition terminal.h:88
std::enable_if_t< meta::is_void_v< Key >, void > set_size(std::size_t size)
Definition terminal.h:119
static constexpr bool is_an_input_terminal
Definition terminal.h:90
std::enable_if_t<!meta::is_void_v< Key >, void > set_size(const Key &key, std::size_t size)
Definition terminal.h:113
meta::detail::finalize_callback_t< keyT > finalize_callback_type
Definition terminal.h:89
static constexpr bool is_an_output_terminal
Definition terminal.h:437
void connect(TerminalBase *in) override
Definition terminal.h:450
std::enable_if_t< meta::is_void_v< Key > &&!meta::is_void_v< Value >, void > sendv(Value &&value)
Definition terminal.h:488
std::enable_if_t< meta::is_none_void_v< Key > &&!meta::is_void_v< valueT >, void > prepare_send(const rangeT &keylist, const Value &value)
Definition terminal.h:588
std::enable_if_t< meta::is_void_v< Key > &&!meta::is_void_v< valueT >, void > prepare_send(const Value &value)
Definition terminal.h:601
std::enable_if_t< meta::is_none_void_v< Key > &&meta::is_void_v< valueT >, void > broadcast(const rangeT &keylist)
Definition terminal.h:575
std::enable_if_t< meta::is_none_void_v< Key, Value >, void > broadcast(const rangeT &keylist, const Value &value)
Definition terminal.h:562
std::enable_if_t<!meta::is_void_v< Key > &&meta::is_void_v< Value >, void > sendk(const Key &key)
Definition terminal.h:476
valueT value_type
Definition terminal.h:432
typename OutTerminalBase< keyT >::key_type key_type
Definition terminal.h:433
std::enable_if_t< meta::is_none_void_v< Key, Value >, void > send(const Key &key, Value &&value)
Definition terminal.h:533
Out()=default
std::enable_if_t< meta::is_all_void_v< Key, Value >, void > send()
Definition terminal.h:515
static constexpr bool is_an_output_terminal
Definition terminal.h:378
std::enable_if_t< meta::is_void_v< Key >, void > finalize()
Definition terminal.h:418
auto nsuccessors() const
Definition terminal.h:390
std::enable_if_t< meta::is_void_v< Key >, void > set_size(std::size_t size)
Definition terminal.h:402
const auto & successors() const
Definition terminal.h:391
std::enable_if_t<!meta::is_void_v< Key >, void > set_size(const Key &key, std::size_t size)
Definition terminal.h:394
std::enable_if_t<!meta::is_void_v< Key >, void > finalize(const Key &key)
Definition terminal.h:410
bool is_pull_terminal
Definition terminal.h:16
void connect_base(TerminalBase *successor)
Definition terminal.h:61
Type get_type() const
Returns the terminal type.
Definition terminal.h:105
void connect_pull(TerminalBase *predecessor)
Definition terminal.h:67
const std::vector< TerminalBase * > & get_connections() const
Get connections to successors.
Definition terminal.h:108
const std::string & get_name() const
Returns name of terminal.
Definition terminal.h:87
Type
describes the terminal type
Definition terminal.h:19
@ Write
can only be written to
@ Read
can only be used to read immutable data
@ Consume
can only be used to read consumable data
A complete version of void.
Definition void.h:12
STL namespace.
typename input_terminals_tuple< keyT, valuesT... >::type input_terminals_tuple_t
Definition terminal.h:355
constexpr bool is_output_terminal_v
detects whether a given type is an output terminal type
Definition terminal.h:616
constexpr bool decays_to_output_terminal_tuple_v
Definition terminal.h:633
constexpr bool is_input_terminal_v
detects whether a given type is an input terminal type
Definition terminal.h:361
constexpr bool is_nonconst_lvalue_reference_to_output_terminal_tuple_v
Definition terminal.h:638
constexpr bool is_output_terminal_tuple_v
Definition terminal.h:630
constexpr auto get(typelist< T, RestOfTs... >)
Definition typelist.h:102
top-level TTG namespace contains runtime-neutral functionality
Definition keymap.h:9
int size(World world=default_execution_context())
Definition run.h:131
int rank(World world=default_execution_context())
Definition run.h:127
void trace(const T &t, const Ts &... ts)
Definition trace.h:44
std::function< size_t(keyT const &key)> owner
Definition terminal.h:28
ContainerWrapper & operator=(const ContainerWrapper &)=default
ContainerWrapper(T &t, mapperT &&mapper, keymapT &&keymap)
Definition terminal.h:38
ContainerWrapper(const ContainerWrapper &)=default
ContainerWrapper(ContainerWrapper &&)=default
std::function< valueT(keyT const &key)> get
Definition terminal.h:27
std::tuple< ttg::In< keyT, valuesT >... > type
Definition terminal.h:346