From 0aece8097e5ab4630efb94bb7f522895df050b39 Mon Sep 17 00:00:00 2001 From: Joseph Schuchart Date: Tue, 26 Oct 2021 14:58:07 -0400 Subject: [PATCH 1/2] Incomplete draft of attributes stored in tuples Signed-off-by: Joseph Schuchart --- ttg/ttg/parsec/ttg.h | 138 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 126 insertions(+), 12 deletions(-) diff --git a/ttg/ttg/parsec/ttg.h b/ttg/ttg/parsec/ttg.h index e261142425..1ece7cd26c 100644 --- a/ttg/ttg/parsec/ttg.h +++ b/ttg/ttg/parsec/ttg.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -2539,25 +2540,138 @@ namespace ttg_parsec { ttg::TTBase::make_executable(); } - /// keymap accessor - /// @return the keymap - const decltype(keymap) &get_keymap() const { return keymap; } + /** + * A set of attributes supported by TTG. + */ + enum class Attribute : size_t { + PRIORITY = 0, + PROCESS, + FINAL, + SOURCE, + IMMEDIATE + }; + + /// priomap setter + /// @arg pm a function that maps a key to an integral priority value. + template + [[deprecated("Use set_attribute_map with Attribute::PRIORITY")]] + void set_priomap(Priomap &&pm) { + set_attribute_map(std::forward(pm)); + } /// keymap setter template void set_keymap(Keymap &&km) { - keymap = km; + set_attribute_map(std::forward(km)); } - /// priority map accessor - /// @return the priority map - const decltype(priomap) &get_priomap() const { return priomap; } + /** + * An attribute value that can store either a fixed value or a function + * to query that value based on a provided key. + */ + template + struct AttributeValue { + using value_type = std::decay_t; + using key_type = std::decay_t; + using function_type = std::function; + private: + std::variant v; + bool has_function = false; + public: - /// priomap setter - /// @arg pm a function that maps a key to an integral priority value. - template - void set_priomap(Priomap &&pm) { - priomap = pm; + AttributeValue() : v(value_type{}) + { } + + template + AttributeValue(Value_&& value) : v(std::forward(value)) + { } + + void set(const function_type& fn) { + std::get<0>(v) = fn; + has_function = true; + } + + void set(function_type&& fn) { + std::get<0>(v) = std::forward(fn); + has_function = true; + } + + void set(const value_type& val) { + std::get<1>(v) = val; + has_function = false; + } + + void set(value_type&& val) { + std::get<1>(v) = std::forward(val); + has_function = false; + } + + value_type get(const KeyT& key) { + return has_function ? std::get<0>(v)(key) : std::get<1>(v); + } + + }; + + + /* Overload for keys of type void */ + template + struct AttributeValue { + using value_type = std::decay_t; + using function_type = std::function; + private: + std::variant v; + bool has_function = false; + public: + + AttributeValue() : v(value_type{}) + { } + + template + AttributeValue(Value_&& value) : v(std::forward(value)) + { } + + void set(const function_type& fn) { + std::get<0>(v) = fn; + } + + void set(function_type&& fn) { + std::get<0>(v) = std::forward(fn); + } + + void set(const value_type& val) { + std::get<1>(v) = val; + } + + void set(value_type&& val) { + std::get<1>(v) = std::forward(val); + } + + value_type get() { + return has_function ? std::get<0>(v)() : std::get<1>(v); + } + + }; + + + std::tuple, + AttributeValue, + AttributeValue, + AttributeValue, + AttributeValue> keymaps; + + template + void set_attribute_map(Map&& op) { + std::get(keymaps).set(std::forward(op)); + } + + template + void set_attribute_value(Value&& val) { + std::get(keymaps).set(std::forward(val)); + } + + template + const auto& get_attribute(KeyT&& key) { + return std::get(keymaps).get(key); } // Register the static_op function to associate it to instance_id From c3a41a425cc3ed78a3f91a45ae425b1d3591f943 Mon Sep 17 00:00:00 2001 From: Joseph Schuchart Date: Thu, 4 Nov 2021 09:13:29 -0400 Subject: [PATCH 2/2] Move attributes into header file and add wrappers for backwards compatibility Signed-off-by: Joseph Schuchart --- ttg/CMakeLists.txt | 1 + ttg/ttg/attributes.h | 147 +++++++++++++++++++++++++++++++++ ttg/ttg/parsec/ttg.h | 188 +++++++++++++++---------------------------- 3 files changed, 215 insertions(+), 121 deletions(-) create mode 100644 ttg/ttg/attributes.h diff --git a/ttg/CMakeLists.txt b/ttg/CMakeLists.txt index c57d971186..c079c85625 100644 --- a/ttg/CMakeLists.txt +++ b/ttg/CMakeLists.txt @@ -26,6 +26,7 @@ set(ttg-base-headers ${CMAKE_CURRENT_SOURCE_DIR}/ttg/base/world.h ) set(ttg-impl-headers + ${CMAKE_CURRENT_SOURCE_DIR}/ttg/attributes.h ${CMAKE_CURRENT_SOURCE_DIR}/ttg/broadcast.h ${CMAKE_CURRENT_SOURCE_DIR}/ttg/edge.h ${CMAKE_CURRENT_SOURCE_DIR}/ttg/execution.h diff --git a/ttg/ttg/attributes.h b/ttg/ttg/attributes.h new file mode 100644 index 0000000000..2239814da6 --- /dev/null +++ b/ttg/ttg/attributes.h @@ -0,0 +1,147 @@ +#ifndef TTG_ATTRIBUTES_H +#define TTG_ATTRIBUTES_H + +namespace ttg { + + + /** + * A set of attributes supported by TTG. + */ + enum class Attribute : size_t { + PRIORITY = 0, + PROCESS, + FINAL, + SOURCE, + IMMEDIATE + }; + + + /** + * An attribute value that can store either a fixed value or a function + * to query that value based on a provided key. + */ + template + struct AttributeValue { + using value_type = std::decay_t; + using key_type = std::decay_t; + using function_type = std::function; + static constexpr const Attribute attribute_id = A; + private: + function_type fn; + value_type val; + public: + + AttributeValue() : val(value_type{}) + { } + + template + AttributeValue(Value_&& value) : val(std::forward(value)) + { } + + template>> + void set(Fn&& fn) { + this->fn = std::forward(fn); + } + + void set(value_type val) { + this->val = val; + this->fn = nullptr; + } + + value_type get(const KeyT& key) const { + return fn ? fn(key) : val; + } + + value_type operator()(const KeyT& key) const { + return get(key); + } + + }; + + + /* Overload for keys of type void */ + template + struct AttributeValue { + using value_type = std::decay_t; + using function_type = std::function; + static constexpr const Attribute attribute_id = A; + private: + function_type fn; + value_type val; + public: + + AttributeValue() : val(value_type{}) + { } + + template + AttributeValue(Value_&& value) : val(std::forward(value)) + { } + + template>> + void set(Fn&& fn) { + this->fn = std::forward(fn); + } + + void set(value_type val) { + this->val = val; + this->fn = nullptr; + } + + value_type get(void) const { + return fn ? fn() : val; + } + + value_type operator()() const { + return get(); + } + + }; + + /* Overload for keys of type ttg::Void */ + template + struct AttributeValue { + using value_type = std::decay_t; + using function_type = std::function; + static constexpr const Attribute attribute_id = A; + private: + function_type fn; + value_type val; + public: + + AttributeValue() : val(value_type{}) + { } + + template + AttributeValue(Value_&& value) : val(std::forward(value)) + { } + + template>> + void set(Fn&& fn) { + this->fn = std::forward(fn); + } + + void set(value_type val) { + this->val = val; + this->fn = nullptr; + } + + value_type get(void) const { + return fn ? fn() : val; + } + + value_type operator()() const { + return get(); + } + + }; + + template + using tt_attribute_set_t = std::tuple, + AttributeValue, + AttributeValue, + AttributeValue, + AttributeValue>; + +} // namespace ttg + +#endif // TTG_ATTRIBUTES_H diff --git a/ttg/ttg/parsec/ttg.h b/ttg/ttg/parsec/ttg.h index 1ece7cd26c..615ffa5b7c 100644 --- a/ttg/ttg/parsec/ttg.h +++ b/ttg/ttg/parsec/ttg.h @@ -11,6 +11,7 @@ /* include ttg header to make symbols available in case this header is included directly */ #include "../../ttg.h" +#include "ttg/attributes.h" #include "ttg/base/keymap.h" #include "ttg/base/tt.h" #include "ttg/base/world.h" @@ -832,8 +833,41 @@ namespace ttg_parsec { make_finalize_argstream_fcts(std::make_index_sequence{}); ttg::World world; - ttg::meta::detail::keymap_t keymap; - ttg::meta::detail::keymap_t priomap; + + ttg::tt_attribute_set_t attributes; + + // wrapper for attribute keymap + template>> + inline int keymap(KeyT&& key) const { + return get_attribute(key); + } + + inline int keymap() const { + if constexpr (ttg::meta::is_void_v) { + return get_attribute().get(); + } else { + // will never be used, but we cannot disable this function using enable_if + throw std::logic_error("UNREACHABLE!"); + } + } + + // wrapper for attribute priomap + template>> + inline + int priomap(KeyT&& key) const { + return get_attribute(key); + } + + inline + int priomap() const { + if constexpr (ttg::meta::is_void_v) { + return get_attribute().get(); + } else { + // will never be used, but we cannot disable this function using enable_if + throw std::logic_error("UNREACHABLE!"); + } + } + // For now use same type for unary/streaming input terminals, and stream reducers assigned at runtime ttg::meta::detail::input_reducers_t input_reducers; //!< Reducers for the input terminals (empty = expect single value) @@ -2315,12 +2349,15 @@ namespace ttg_parsec { ttg::World world, keymapT &&keymap_ = keymapT(), priomapT &&priomap_ = priomapT() ) : ttg::TTBase(name, numins, numouts) , world(world) - // if using default keymap, rebind to the given world - , keymap(std::is_same>::value - ? decltype(keymap)(ttg::detail::default_keymap(world)) - : decltype(keymap)(std::forward(keymap_))) - , priomap(decltype(keymap)(std::forward(priomap_))) , static_stream_goal() { + + // if using default keymap, rebind to the given world + if constexpr (std::is_same>::value) { + set_attribute(ttg::detail::default_keymap(world)); + } else { + set_attribute(keymap_); + } + // Cannot call these in base constructor since terminals not yet constructed if (innames.size() != std::tuple_size::value) throw std::logic_error("ttg_parsec::OP: #input names != #input terminals"); @@ -2540,138 +2577,47 @@ namespace ttg_parsec { ttg::TTBase::make_executable(); } - /** - * A set of attributes supported by TTG. - */ - enum class Attribute : size_t { - PRIORITY = 0, - PROCESS, - FINAL, - SOURCE, - IMMEDIATE - }; - /// priomap setter /// @arg pm a function that maps a key to an integral priority value. template [[deprecated("Use set_attribute_map with Attribute::PRIORITY")]] void set_priomap(Priomap &&pm) { - set_attribute_map(std::forward(pm)); + set_attribute(std::forward(pm)); } /// keymap setter template + [[deprecated("Use set_attribute_map with Attribute::PROCESS")]] void set_keymap(Keymap &&km) { - set_attribute_map(std::forward(km)); + set_attribute(std::forward(km)); } - /** - * An attribute value that can store either a fixed value or a function - * to query that value based on a provided key. - */ - template - struct AttributeValue { - using value_type = std::decay_t; - using key_type = std::decay_t; - using function_type = std::function; - private: - std::variant v; - bool has_function = false; - public: - - AttributeValue() : v(value_type{}) - { } - - template - AttributeValue(Value_&& value) : v(std::forward(value)) - { } - - void set(const function_type& fn) { - std::get<0>(v) = fn; - has_function = true; - } - - void set(function_type&& fn) { - std::get<0>(v) = std::forward(fn); - has_function = true; - } - - void set(const value_type& val) { - std::get<1>(v) = val; - has_function = false; - } - - void set(value_type&& val) { - std::get<1>(v) = std::forward(val); - has_function = false; - } - - value_type get(const KeyT& key) { - return has_function ? std::get<0>(v)(key) : std::get<1>(v); - } - - }; - - - /* Overload for keys of type void */ - template - struct AttributeValue { - using value_type = std::decay_t; - using function_type = std::function; - private: - std::variant v; - bool has_function = false; - public: - - AttributeValue() : v(value_type{}) - { } - - template - AttributeValue(Value_&& value) : v(std::forward(value)) - { } - - void set(const function_type& fn) { - std::get<0>(v) = fn; - } - - void set(function_type&& fn) { - std::get<0>(v) = std::forward(fn); - } - - void set(const value_type& val) { - std::get<1>(v) = val; - } - - void set(value_type&& val) { - std::get<1>(v) = std::forward(val); - } - - value_type get() { - return has_function ? std::get<0>(v)() : std::get<1>(v); - } - - }; - + template + void set_attribute(ValueOrFnT&& x) { + static_assert(std::tuple_element_t<(size_t)A, ttg::tt_attribute_set_t>::attribute_id == A, "Someone broke the attributes order!"); + std::get<(size_t)A>(attributes).set(std::forward(x)); + } - std::tuple, - AttributeValue, - AttributeValue, - AttributeValue, - AttributeValue> keymaps; + template>> + const auto get_attribute(KeyT&& key) const { + static_assert(std::tuple_element_t<(size_t)A, ttg::tt_attribute_set_t>::attribute_id == A, "Someone broke the attributes order!"); + return std::get<(size_t)A>(attributes).get(key); + } - template - void set_attribute_map(Map&& op) { - std::get(keymaps).set(std::forward(op)); + template>> + const auto get_attribute() const { + static_assert(std::tuple_element_t<(size_t)A, ttg::tt_attribute_set_t>::attribute_id == A, "Someone broke the attributes order!"); + return std::get<(size_t)A>(attributes).get(); } - template - void set_attribute_value(Value&& val) { - std::get(keymaps).set(std::forward(val)); + template + const auto& get_attribute(void) const { + static_assert(std::tuple_element_t<(size_t)A, ttg::tt_attribute_set_t>::attribute_id == A, "Someone broke the attributes order!"); + return std::get<(size_t)A>(attributes); } - template - const auto& get_attribute(KeyT&& key) { - return std::get(keymaps).get(key); + inline const auto& get_keymap() const { + return get_attribute(); } // Register the static_op function to associate it to instance_id