Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ttg/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
147 changes: 147 additions & 0 deletions ttg/ttg/attributes.h
Original file line number Diff line number Diff line change
@@ -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<Attribute A, typename KeyT, typename ValueT>
struct AttributeValue {
using value_type = std::decay_t<ValueT>;
using key_type = std::decay_t<KeyT>;
using function_type = std::function<value_type(const key_type&)>;
static constexpr const Attribute attribute_id = A;
private:
function_type fn;
value_type val;
public:

AttributeValue() : val(value_type{})
{ }

template<typename Value_>
AttributeValue(Value_&& value) : val(std::forward<Value_>(value))
{ }

template<typename Fn, typename = std::enable_if_t<std::is_invocable_r_v<ValueT, Fn, KeyT>>>
void set(Fn&& fn) {
this->fn = std::forward<Fn>(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<Attribute A, typename ValueT>
struct AttributeValue<A, void, ValueT> {
using value_type = std::decay_t<ValueT>;
using function_type = std::function<value_type(void)>;
static constexpr const Attribute attribute_id = A;
private:
function_type fn;
value_type val;
public:

AttributeValue() : val(value_type{})
{ }

template<typename Value_>
AttributeValue(Value_&& value) : val(std::forward<Value_>(value))
{ }

template<typename Fn, typename = std::enable_if_t<std::is_invocable_v<Fn>>>
void set(Fn&& fn) {
this->fn = std::forward<Fn>(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<Attribute A, typename ValueT>
struct AttributeValue<A, ttg::Void, ValueT> {
using value_type = std::decay_t<ValueT>;
using function_type = std::function<value_type(void)>;
static constexpr const Attribute attribute_id = A;
private:
function_type fn;
value_type val;
public:

AttributeValue() : val(value_type{})
{ }

template<typename Value_>
AttributeValue(Value_&& value) : val(std::forward<Value_>(value))
{ }

template<typename Fn, typename = std::enable_if_t<std::is_invocable_v<Fn>>>
void set(Fn&& fn) {
this->fn = std::forward<Fn>(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<typename KeyT>
using tt_attribute_set_t = std::tuple<AttributeValue<Attribute::PRIORITY, KeyT, int32_t>,
AttributeValue<Attribute::PROCESS, KeyT, int32_t>,
AttributeValue<Attribute::FINAL, KeyT, bool>,
AttributeValue<Attribute::SOURCE, KeyT, bool>,
AttributeValue<Attribute::IMMEDIATE, KeyT, bool>>;

} // namespace ttg

#endif // TTG_ATTRIBUTES_H
98 changes: 79 additions & 19 deletions ttg/ttg/parsec/ttg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -43,6 +44,7 @@
#include <string>
#include <tuple>
#include <vector>
#include <variant>

#include <parsec.h>
#include <parsec/class/parsec_hash_table.h>
Expand Down Expand Up @@ -831,8 +833,41 @@ namespace ttg_parsec {
make_finalize_argstream_fcts(std::make_index_sequence<numins>{});

ttg::World world;
ttg::meta::detail::keymap_t<keyT> keymap;
ttg::meta::detail::keymap_t<keyT> priomap;

ttg::tt_attribute_set_t<keyT> attributes;

// wrapper for attribute keymap
template<typename KeyT, typename = std::enable_if_t<!ttg::meta::is_void_v<KeyT>>>
inline int keymap(KeyT&& key) const {
return get_attribute<ttg::Attribute::PROCESS>(key);
}

inline int keymap() const {
if constexpr (ttg::meta::is_void_v<keyT>) {
return get_attribute<ttg::Attribute::PROCESS>().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<typename KeyT, typename = std::enable_if_t<!ttg::meta::is_void_v<KeyT>>>
inline
int priomap(KeyT&& key) const {
return get_attribute<ttg::Attribute::PRIORITY>(key);
}

inline
int priomap() const {
if constexpr (ttg::meta::is_void_v<keyT>) {
return get_attribute<ttg::Attribute::PRIORITY>().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_valueTs...>
input_reducers; //!< Reducers for the input terminals (empty = expect single value)
Expand Down Expand Up @@ -2314,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<keymapT, ttg::detail::default_keymap<keyT>>::value
? decltype(keymap)(ttg::detail::default_keymap<keyT>(world))
: decltype(keymap)(std::forward<keymapT>(keymap_)))
, priomap(decltype(keymap)(std::forward<priomapT>(priomap_)))
, static_stream_goal() {

// if using default keymap, rebind to the given world
if constexpr (std::is_same<keymapT, ttg::detail::default_keymap<keyT>>::value) {
set_attribute<ttg::Attribute::PROCESS>(ttg::detail::default_keymap<keyT>(world));
} else {
set_attribute<ttg::Attribute::PROCESS>(keymap_);
}

// Cannot call these in base constructor since terminals not yet constructed
if (innames.size() != std::tuple_size<input_terminals_type>::value)
throw std::logic_error("ttg_parsec::OP: #input names != #input terminals");
Expand Down Expand Up @@ -2539,25 +2577,47 @@ namespace ttg_parsec {
ttg::TTBase::make_executable();
}

/// keymap accessor
/// @return the keymap
const decltype(keymap) &get_keymap() const { return keymap; }
/// priomap setter
/// @arg pm a function that maps a key to an integral priority value.
template <typename Priomap>
[[deprecated("Use set_attribute_map with Attribute::PRIORITY")]]
void set_priomap(Priomap &&pm) {
set_attribute<ttg::Attribute::PRIORITY>(std::forward<Priomap>(pm));
}

/// keymap setter
template <typename Keymap>
[[deprecated("Use set_attribute_map with Attribute::PROCESS")]]
void set_keymap(Keymap &&km) {
keymap = km;
set_attribute<ttg::Attribute::PROCESS>(std::forward<Keymap>(km));
}

/// priority map accessor
/// @return the priority map
const decltype(priomap) &get_priomap() const { return priomap; }
template<ttg::Attribute A, typename ValueOrFnT>
void set_attribute(ValueOrFnT&& x) {
static_assert(std::tuple_element_t<(size_t)A, ttg::tt_attribute_set_t<keyT>>::attribute_id == A, "Someone broke the attributes order!");
std::get<(size_t)A>(attributes).set(std::forward<ValueOrFnT>(x));
}

/// priomap setter
/// @arg pm a function that maps a key to an integral priority value.
template <typename Priomap>
void set_priomap(Priomap &&pm) {
priomap = pm;
template<ttg::Attribute A, typename KeyT, typename = std::enable_if_t<!std::is_void_v<KeyT>>>
const auto get_attribute(KeyT&& key) const {
static_assert(std::tuple_element_t<(size_t)A, ttg::tt_attribute_set_t<keyT>>::attribute_id == A, "Someone broke the attributes order!");
return std::get<(size_t)A>(attributes).get(key);
}

template<ttg::Attribute A, typename KeyT, typename = std::enable_if_t<std::is_void_v<KeyT>>>
const auto get_attribute() const {
static_assert(std::tuple_element_t<(size_t)A, ttg::tt_attribute_set_t<keyT>>::attribute_id == A, "Someone broke the attributes order!");
return std::get<(size_t)A>(attributes).get();
}

template<ttg::Attribute A>
const auto& get_attribute(void) const {
static_assert(std::tuple_element_t<(size_t)A, ttg::tt_attribute_set_t<keyT>>::attribute_id == A, "Someone broke the attributes order!");
return std::get<(size_t)A>(attributes);
}

inline const auto& get_keymap() const {
return get_attribute<ttg::Attribute::PROCESS>();
}

// Register the static_op function to associate it to instance_id
Expand Down