diff --git a/CMakePresets.json b/CMakePresets.json index 79b4a20a..dc1d73c2 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -5,7 +5,7 @@ "hidden": false, "cacheVariables": { "CMAKE_EXPORT_COMPILE_COMMANDS": "YES", - "CMAKE_CXX_STANDARD": "20", + "CMAKE_CXX_STANDARD": "23", "CMAKE_CXX_STANDARD_REQUIRED": "YES", "CMAKE_CXX_EXTENSIONS": "NO", "CMAKE_PROJECT_TOP_LEVEL_INCLUDES": "CetProvideDependency" diff --git a/ci/spack.yaml b/ci/spack.yaml index 616d9fdf..71d68acc 100644 --- a/ci/spack.yaml +++ b/ci/spack.yaml @@ -29,7 +29,7 @@ spack: phlex: require: - "+form" - - "cxxstd=20" + - "cxxstd=23" - "%gcc@15" @@ -49,4 +49,4 @@ spack: root: require: - "~x" # No graphics libraries required - - "cxxstd=20" + - "cxxstd=23" diff --git a/phlex/configuration.cpp b/phlex/configuration.cpp index 03cb6daa..06150580 100644 --- a/phlex/configuration.cpp +++ b/phlex/configuration.cpp @@ -1,8 +1,55 @@ #include "phlex/configuration.hpp" #include "phlex/core/product_query.hpp" -#include +#include +#include #include +#include + +namespace { + std::optional value_if_exists(boost::json::object const& obj, + std::string_view parameter) + { + if (!obj.contains(parameter)) { + return std::nullopt; + } + auto const& val = obj.at(parameter); + if (!val.is_string()) { + std::string_view kind; + switch (val.kind()) { + case boost::json::kind::null: + // seems reasonable to interpret this as if the value were not provided + return std::nullopt; + break; + case boost::json::kind::bool_: + kind = "bool"; + break; + case boost::json::kind::int64: + kind = "std::int64_t"; + break; + case boost::json::kind::uint64: + kind = "std::uint64_t"; + break; + case boost::json::kind::double_: + kind = "double"; + break; + case boost::json::kind::array: + kind = "array"; + break; + case boost::json::kind::object: + kind = "object"; + break; + default: + std::unreachable(); + } + throw std::runtime_error(fmt::format( + "Error retrieving parameter '{}'. Should be an identifier string but is instead a {}", + parameter, + kind)); + } + return boost::json::value_to(val); + } +} namespace phlex { std::vector configuration::keys() const @@ -25,7 +72,11 @@ namespace phlex { { using detail::value_decorate_exception; auto query_object = jv.as_object(); - return product_query{{value_decorate_exception(query_object, "product")}, - value_decorate_exception(query_object, "layer")}; + auto creator = value_decorate_exception(query_object, "creator"); + auto layer = value_decorate_exception(query_object, "layer"); + auto suffix = value_if_exists(query_object, "suffix"); + auto stage = value_if_exists(query_object, "stage"); + return product_query{ + .creator = std::move(creator), .layer = std::move(layer), .suffix = suffix, .stage = stage}; } } diff --git a/phlex/configuration.hpp b/phlex/configuration.hpp index 1fa142b8..82ef7aa3 100644 --- a/phlex/configuration.hpp +++ b/phlex/configuration.hpp @@ -19,6 +19,14 @@ namespace phlex { } catch (std::exception const& e) { throw std::runtime_error("Error retrieving parameter '" + key + "':\n" + e.what()); } + + // helper for unpacking json array + template + std::array unpack_json_array(boost::json::array const& array, + std::index_sequence) + { + return std::array{boost::json::value_to(array.at(I))...}; + } } class configuration { @@ -81,6 +89,19 @@ namespace phlex { product_query tag_invoke(boost::json::value_to_tag const&, boost::json::value const& jv); + + template + std::array tag_invoke( + boost::json::value_to_tag> const&, boost::json::value const& jv) + { + auto const& array = jv.as_array(); + return detail::unpack_json_array(array, std::make_index_sequence()); + } } +// The below is a better long term fix but it requires a Boost JSON bug (#1140) to be fixed +// namespace boost::json { +// template +// struct is_sequence_like> : std::false_type {}; +// } #endif // PHLEX_CONFIGURATION_HPP diff --git a/phlex/core/detail/filter_impl.cpp b/phlex/core/detail/filter_impl.cpp index a7156cc9..ce9d19dd 100644 --- a/phlex/core/detail/filter_impl.cpp +++ b/phlex/core/detail/filter_impl.cpp @@ -5,12 +5,8 @@ #include namespace { - phlex::product_query const output_dummy{ - phlex::experimental::product_specification{ - phlex::experimental::algorithm_name{"for_output_only", ""}, - "for_output_only", - phlex::experimental::type_id{}}, - "dummy_layer"}; + phlex::product_query const output_dummy = phlex::product_query{ + .creator = "for_output_only"_id, .layer = "dummy_layer"_id, .suffix = "for_output_only"_id}; phlex::product_queries const for_output_only{output_dummy}; } diff --git a/phlex/core/edge_creation_policy.cpp b/phlex/core/edge_creation_policy.cpp index 1ab4ab71..dfe1e272 100644 --- a/phlex/core/edge_creation_policy.cpp +++ b/phlex/core/edge_creation_policy.cpp @@ -9,55 +9,55 @@ namespace phlex::experimental { edge_creation_policy::named_output_port const* edge_creation_policy::find_producer( product_query const& query) const { - auto const& spec = query.spec(); - auto [b, e] = producers_.equal_range(spec.name()); + // TODO: Update later with correct querying + auto [b, e] = producers_.equal_range(std::string(query.suffix.value_or(""_id))); if (b == e) { spdlog::debug( "Failed to find an algorithm that creates {} products. Assuming it comes from a provider", - spec.name()); + query.suffix.value_or("\"\""_id)); return nullptr; } std::map candidates; for (auto const& [key, producer] : std::ranges::subrange{b, e}) { - if (producer.node.match(spec.qualifier())) { - if (spec.type() != producer.type) { - spdlog::debug("Matched {} ({}) from {} but types don't match (`{}` vs `{}`). Excluding " + // TODO: Definitely not right yet + if (producer.node.plugin() == std::string_view(query.creator) || + producer.node.algorithm() == std::string_view(query.creator)) { + if (query.type != producer.type) { + spdlog::debug("Matched ({}) from {} but types don't match (`{}` vs `{}`). Excluding " "from candidate list.", - spec.full(), query.to_string(), producer.node.full(), - spec.type(), + query.type, producer.type); } else { - if (spec.type().exact_compare(producer.type)) { - spdlog::debug("Matched {} ({}) from {} and types match. Keeping in candidate list.", - spec.full(), + if (query.type.exact_compare(producer.type)) { + spdlog::debug("Matched ({}) from {} and types match. Keeping in candidate list.", query.to_string(), producer.node.full()); } else { - spdlog::warn("Matched {} ({}) from {} and types match, but not exactly (produce {} and " + spdlog::warn("Matched ({}) from {} and types match, but not exactly (produce {} and " "consume {}). Keeping in candidate list!", - spec.full(), query.to_string(), producer.node.full(), - spec.type().exact_name(), + query.type.exact_name(), producer.type.exact_name()); } candidates.emplace(producer.node.full(), &producer); } + } else { + spdlog::error( + "Creator name mismatch between ({}) and {}", query.to_string(), producer.node.full()); } } if (candidates.empty()) { - throw std::runtime_error("Cannot identify product matching the specified label " + - spec.full()); + throw std::runtime_error("Cannot identify product matching the query " + query.to_string()); } if (candidates.size() > 1ull) { - std::string msg = - fmt::format("More than one candidate matches the specification {}: \n - {}\n", - spec.full(), - fmt::join(std::views::keys(candidates), "\n - ")); + std::string msg = fmt::format("More than one candidate matches the query {}: \n - {}\n", + query.to_string(), + fmt::join(std::views::keys(candidates), "\n - ")); throw std::runtime_error(msg); } diff --git a/phlex/core/edge_maker.cpp b/phlex/core/edge_maker.cpp index 9f9e3362..153c5d38 100644 --- a/phlex/core/edge_maker.cpp +++ b/phlex/core/edge_maker.cpp @@ -19,7 +19,7 @@ namespace phlex::experimental { bool found_match = false; for (auto const& [_, p] : providers) { auto& provider = *p; - if (port.product_label == provider.output_product()) { + if (port.product_label.match(provider.output_product())) { auto it = result.find(provider.full_name()); if (it == result.cend()) { result.try_emplace(provider.full_name(), port.product_label, provider.input_port()); diff --git a/phlex/core/multiplexer.cpp b/phlex/core/multiplexer.cpp index 9c60b7c8..a79e2702 100644 --- a/phlex/core/multiplexer.cpp +++ b/phlex/core/multiplexer.cpp @@ -15,7 +15,7 @@ using namespace phlex::experimental; namespace { product_store_const_ptr store_for(product_store_const_ptr store, - std::string const& port_product_layer) + std::string_view port_product_layer) { if (store->id()->layer_name() == port_product_layer) { // This store's layer matches what is expected by the port @@ -66,7 +66,7 @@ namespace phlex::experimental { auto start_time = steady_clock::now(); for (auto const& [product_label, port] : provider_input_ports_ | std::views::values) { - if (auto store_to_send = store_for(store, product_label.layer())) { + if (auto store_to_send = store_for(store, product_label.layer)) { port->try_put({std::move(store_to_send), eom, message_id}); } } diff --git a/phlex/core/product_query.cpp b/phlex/core/product_query.cpp index 5f442e70..3b49d0d5 100644 --- a/phlex/core/product_query.cpp +++ b/phlex/core/product_query.cpp @@ -2,37 +2,82 @@ #include "fmt/format.h" -#include - namespace phlex { - product_query::product_query() = default; - - product_query::product_query(experimental::product_specification spec, std::string layer) : - spec_{std::move(spec)}, layer_{std::move(layer)} + // Check that all products selected by /other/ would satisfy this query + bool product_query::match(product_query const& other) const { + using experimental::identifier; + if (identifier(creator) != identifier(other.creator)) { + return false; + } + if (identifier(layer) != identifier(other.layer)) { + return false; + } + if (suffix && suffix != other.suffix) { + return false; + } + if (stage && stage != other.stage) { + return false; + } + // Special case. If other has an unset type_id, ignore this in case it just hasn't been set yet + if (type.valid() && other.type.valid() && type != other.type) { + return false; + } + return true; } - product_query experimental::product_tag::operator()(std::string data_layer) && + // Check if a product_specification satisfies this query + bool product_query::match(experimental::product_specification const& spec) const { - if (data_layer.empty()) { - throw std::runtime_error("Cannot specify the empty string as a data layer."); + // string comparisons for now for a gradual transition + if (std::string_view(creator) != spec.algorithm()) { + return false; } - return {std::move(spec), std::move(data_layer)}; + if (type != spec.type()) { + return false; + } + if (suffix) { + if (std::string_view(*suffix) != spec.name()) { + return false; + } + } + return true; } std::string product_query::to_string() const { - if (layer_.empty()) { - return spec_.full(); + if (suffix) { + return fmt::format("{}/{} ϵ {}", creator, *suffix, layer); } - return fmt::format("{} ϵ {}", spec_.full(), layer_); + return fmt::format("{} ϵ {}", creator, layer); } - experimental::product_tag operator""_in(char const* product_name, std::size_t length) + experimental::product_specification product_query::spec() const { - if (length == 0ull) { - throw std::runtime_error("Cannot specify product with empty name."); + if (!suffix) { + throw std::logic_error("Product suffixes are (temporarily) mandatory"); } - return {experimental::product_specification::create(product_name)}; + // Not efficient, but this should be temporary + return experimental::product_specification::create(std::string(*suffix)); + } + bool product_query::operator==(product_query const& rhs) const + { + using experimental::identifier; + return (type == rhs.type) && (identifier(creator) == identifier(rhs.creator)) && + (identifier(layer) == identifier(rhs.layer)) && (suffix == rhs.suffix) && + (stage == rhs.stage); + } + std::strong_ordering product_query::operator<=>(product_query const& rhs) const + { + using experimental::identifier; + return std::tie(type, + static_cast(creator), + static_cast(layer), + suffix, + stage) <=> std::tie(rhs.type, + static_cast(rhs.creator), + static_cast(rhs.layer), + rhs.suffix, + rhs.stage); } } diff --git a/phlex/core/product_query.hpp b/phlex/core/product_query.hpp index 55cc3956..889cde67 100644 --- a/phlex/core/product_query.hpp +++ b/phlex/core/product_query.hpp @@ -1,47 +1,93 @@ #ifndef PHLEX_CORE_PRODUCT_QUERY_HPP #define PHLEX_CORE_PRODUCT_QUERY_HPP +#include "phlex/model/identifier.hpp" #include "phlex/model/product_specification.hpp" +#include "phlex/model/type_id.hpp" -// #include +#include #include +#include #include +// Used for the _id and _idq literals +using namespace phlex::experimental::literals; + namespace phlex { - class product_query { - public: - // FIXME: Boost JSON's parameter retrieval facilities require a default constructor - // whenever the type is (e.g.) std::array. - product_query(); - product_query(experimental::product_specification spec, std::string layer); + namespace detail { + template + requires std::is_same_v // has to be a template for static_assert(false) + class required_creator_name { + public: + consteval required_creator_name() + { + static_assert(false, "The creator name has not been set in this product_query."); + } + required_creator_name(T&& rhs) : content_(std::move(rhs)) + { + if (content_.empty()) { + throw std::runtime_error("Cannot specify product with empty creator name."); + } + } - auto const& spec() const noexcept { return spec_; } - auto const& layer() const noexcept { return layer_; } - void set_type(experimental::type_id&& type) { spec_.set_type(std::move(type)); } + operator T const&() const noexcept { return content_; } - std::string to_string() const; + private: + experimental::identifier content_; + }; - auto operator<=>(product_query const&) const = default; + template + requires std::is_same_v // has to be a template for static_assert(false) + class required_layer_name { + public: + consteval required_layer_name() + { + static_assert(false, "The layer name has not been set in this product_query."); + } + required_layer_name(T&& rhs) : content_(std::move(rhs)) + { + if (content_.empty()) { + throw std::runtime_error("Cannot specify the empty string as a data layer."); + } + } - private: - experimental::product_specification spec_; - std::string layer_; - }; + operator T const&() const noexcept { return content_; } - using product_queries = std::vector; -} + private: + experimental::identifier content_; + }; + } + + struct product_query { + detail::required_creator_name creator; + detail::required_layer_name layer; + std::optional suffix; + std::optional stage; + experimental::type_id type; + + // Check that all products selected by /other/ would satisfy this query + bool match(product_query const& other) const; + + // Check if a product_specification satisfies this query + bool match(experimental::product_specification const& spec) const; -namespace phlex::experimental { - struct product_tag { - product_specification spec; - product_query operator()(std::string layer) &&; + std::string to_string() const; + + bool operator==(product_query const& rhs) const; + std::strong_ordering operator<=>(product_query const& rhs) const; + + // temporary additional members for transition + experimental::product_specification spec() const; }; + using product_queries = std::vector; namespace detail { // C is a container of product_queries template requires std::is_same_v::value_type, product_query> && - is_tuple::value + experimental::is_tuple::value class product_queries_type_setter {}; template class product_queries_type_setter> { @@ -51,7 +97,7 @@ namespace phlex::experimental { template void set_type(C& container) { - container.at(index_).set_type(make_type_id()); + container.at(index_).type = experimental::make_type_id(); ++index_; } @@ -66,7 +112,7 @@ namespace phlex::experimental { template requires std::is_same_v::value_type, product_query> && - is_tuple::value + experimental::is_tuple::value void populate_types(C& container) { detail::product_queries_type_setter populate_types{}; @@ -74,8 +120,4 @@ namespace phlex::experimental { } } -namespace phlex { - experimental::product_tag operator""_in(char const* str, std::size_t); -} - #endif // PHLEX_CORE_PRODUCT_QUERY_HPP diff --git a/phlex/core/registration_api.hpp b/phlex/core/registration_api.hpp index 66ceae60..e11bb6b3 100644 --- a/phlex/core/registration_api.hpp +++ b/phlex/core/registration_api.hpp @@ -136,7 +136,7 @@ namespace phlex::experimental { using return_type = return_type; using provider_type = provider_node; - output.set_type(make_type_id()); + output.type = make_type_id(); registrar_.set_creator( [this, output = std::move(output)](auto /* predicates */, auto /* output_products */) { diff --git a/phlex/model/CMakeLists.txt b/phlex/model/CMakeLists.txt index 0c4ae679..256bae49 100644 --- a/phlex/model/CMakeLists.txt +++ b/phlex/model/CMakeLists.txt @@ -7,6 +7,7 @@ cet_make_library( data_cell_counter.cpp data_layer_hierarchy.cpp data_cell_index.cpp + identifier.cpp product_matcher.cpp product_store.cpp products.cpp @@ -30,6 +31,7 @@ install( data_cell_counter.hpp data_layer_hierarchy.hpp data_cell_index.hpp + identifier.hpp product_matcher.hpp product_specification.hpp product_store.hpp diff --git a/phlex/model/data_cell_index.cpp b/phlex/model/data_cell_index.cpp index 533a80dd..42e1cff5 100644 --- a/phlex/model/data_cell_index.cpp +++ b/phlex/model/data_cell_index.cpp @@ -110,7 +110,7 @@ namespace phlex { data_cell_index_ptr data_cell_index::parent() const noexcept { return parent_; } - data_cell_index_ptr data_cell_index::parent(std::string const& layer_name) const + data_cell_index_ptr data_cell_index::parent(std::string_view layer_name) const { data_cell_index_ptr parent = parent_; while (parent) { diff --git a/phlex/model/data_cell_index.hpp b/phlex/model/data_cell_index.hpp index 3e70752f..3cebad72 100644 --- a/phlex/model/data_cell_index.hpp +++ b/phlex/model/data_cell_index.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -22,7 +23,7 @@ namespace phlex { std::string const& layer_name() const noexcept; std::string layer_path() const; std::size_t depth() const noexcept; - data_cell_index_ptr parent(std::string const& layer_name) const; + data_cell_index_ptr parent(std::string_view layer_name) const; data_cell_index_ptr parent() const noexcept; bool has_parent() const noexcept; std::size_t number() const; diff --git a/phlex/model/identifier.cpp b/phlex/model/identifier.cpp new file mode 100644 index 00000000..c8e5a0ad --- /dev/null +++ b/phlex/model/identifier.cpp @@ -0,0 +1,93 @@ +#include "identifier.hpp" + +#include +#include + +namespace phlex::experimental { + identifier_query literals::operator""_idq(char const* lit, std::size_t len) + { + return {identifier::hash_string(std::string_view(lit, len))}; + } + + std::uint64_t identifier::hash_string(std::string_view const& str) + { + // Hash quality is very important here, since comparisons are done using only the hash + using namespace boost::hash2; + xxhash_64 h; + hash_append(h, {}, str); + return h.result(); + } + + identifier::identifier(std::string_view const& str) : + content_(std::make_shared(str)), hash_(hash_string(*content_)) + { + // Can't put this in the initializer list because the base is initialized before content_ + *static_cast(this) = *content_; + } + identifier::identifier(identifier const& other) : + std::string_view(other), content_(other.content_), hash_(other.hash_) + { + } + identifier::identifier(identifier&& other) noexcept : + content_(std::move(other.content_)), hash_(other.hash_) + { + // Can't put this in the initializer list because the base is initialized before content_ + *static_cast(this) = *content_; + static_cast(other) = std::string_view{}; + other.hash_ = 0; + } + identifier::identifier(char const* lit) : identifier(std::string_view(lit)) {} + identifier& identifier::operator=(std::string_view const& str) + { + content_ = std::make_shared(str); + hash_ = hash_string(*content_); + *static_cast(this) = *content_; + return *this; + } + identifier& identifier::operator=(char const* lit) + { + this->operator=(std::string_view{lit}); + return *this; + } + identifier& identifier::operator=(identifier const& rhs) + { + if (&rhs == this) { + return *this; + } + content_ = rhs.content_; + hash_ = rhs.hash_; + *static_cast(this) = *content_; + return *this; + } + identifier& identifier::operator=(identifier&& rhs) noexcept + { + content_ = std::move(rhs.content_); + hash_ = rhs.hash_; + rhs.hash_ = 0; + *static_cast(this) = *content_; + static_cast(rhs) = std::string_view{}; + return *this; + } + identifier::~identifier() + { + // clear the string_view before content_ is deleted + *static_cast(this) = std::string_view{}; + hash_ = 0; + } + bool identifier::operator==(identifier const& rhs) const noexcept { return hash_ == rhs.hash_; } + std::strong_ordering identifier::operator<=>(identifier const& rhs) const noexcept + { + return hash_ <=> rhs.hash_; + } + + bool operator==(identifier const& lhs, identifier_query rhs) { return lhs.hash_ == rhs.hash; } + std::strong_ordering operator<=>(identifier const& lhs, identifier_query rhs) + { + return lhs.hash_ <=> rhs.hash; + } + + identifier literals::operator""_id(char const* lit, std::size_t len) + { + return identifier{std::string_view(lit, len)}; + } +} diff --git a/phlex/model/identifier.hpp b/phlex/model/identifier.hpp new file mode 100644 index 00000000..31d6b702 --- /dev/null +++ b/phlex/model/identifier.hpp @@ -0,0 +1,81 @@ +#ifndef PHLEX_MODEL_IDENTIFIER_H_ +#define PHLEX_MODEL_IDENTIFIER_H_ + +#include + +#include + +#include +#include +#include +#include + +namespace phlex::experimental { + /// If you're comparing to an identifier you know at compile time, you're probably not going to need + /// to print it. + struct identifier_query { + std::uint64_t hash; + }; + + /// Carries around the string itself (as a shared_ptr to string to make copies lighter) + /// along with a precomputed hash used for all comparisons + class identifier : public std::string_view { + public: + static std::uint64_t hash_string(std::string_view const& str); + identifier(identifier const& other); + identifier(identifier&& other) noexcept; + + // Standard constructor for identifiers read from a file + identifier(std::string_view const& str); + // Constructor for creating identifiers in code + // Is it confusing that the _id syntax does something different? + identifier(char const* lit); + + identifier& operator=(identifier const& rhs); + identifier& operator=(identifier&& rhs) noexcept; + + // Assignment for identifiers read from a file + identifier& operator=(std::string_view const& str); + // Assignment for identifiers in code + identifier& operator=(char const* lit); + + ~identifier(); + + bool operator==(identifier const& rhs) const noexcept; + std::strong_ordering operator<=>(identifier const& rhs) const noexcept; + + // Comparison operators with _id queries + friend bool operator==(identifier const& lhs, identifier_query rhs); + friend std::strong_ordering operator<=>(identifier const& lhs, identifier_query rhs); + friend std::hash; + + private: + std::shared_ptr content_; + std::uint64_t hash_; + }; + + // Identifier UDL + namespace literals { + identifier operator""_id(char const* lit, std::size_t len); + identifier_query operator""_idq(char const* lit, std::size_t len); + } + + // Heterogeneous operators are disabled to avoid accidentally getting an incorrect result + bool operator==(identifier const& lhs, std::string_view const& rhs) = delete; + std::strong_ordering operator<=>(identifier const& lhs, std::string_view const& rhs) = delete; + // Really trying to avoid the extra function call here + inline std::string_view format_as(identifier const& id) + { + return static_cast(id); + } +} + +template <> +struct std::hash { + std::size_t operator()(phlex::experimental::identifier const& id) const noexcept + { + return id.hash_; + } +}; + +#endif // PHLEX_MODEL_IDENTIFIER_H_ diff --git a/phlex/model/type_id.hpp b/phlex/model/type_id.hpp index ec6399dd..080f3e88 100644 --- a/phlex/model/type_id.hpp +++ b/phlex/model/type_id.hpp @@ -7,6 +7,7 @@ #include "fmt/format.h" #include "fmt/ranges.h" #include +#include #include #include @@ -43,6 +44,19 @@ namespace phlex::experimental { constexpr builtin fundamental() const { return static_cast(id_ & 0x0F); } + template + friend constexpr void tag_invoke(boost::hash2::hash_append_tag const&, + Provider const&, + Hash& h, + Flavor const& f, + type_id const* v) + { + boost::hash2::hash_append(h, f, v->id_); + if (v->has_children()) { + boost::hash2::hash_append(h, f, v->children_); + } + } + constexpr std::strong_ordering operator<=>(type_id const& rhs) const { // This ordering is arbitrary but defined diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 63a32a9e..af71df3f 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1,7 +1,7 @@ # Phlex provided core plugins # plugin for running Python algorithms in phlex -add_subdirectory(python) +# add_subdirectory(python) add_library(layer_generator layer_generator.cpp) target_link_libraries(layer_generator PRIVATE phlex::core) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ab51b55f..d0b8e237 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -236,7 +236,7 @@ add_subdirectory(plugins) add_subdirectory(utilities) add_subdirectory(mock-workflow) add_subdirectory(demo-giantdata) -add_subdirectory(python) +# add_subdirectory(python) if(PHLEX_USE_FORM) add_subdirectory(form) diff --git a/test/allowed_families.cpp b/test/allowed_families.cpp index d0f3a54f..2a92b08c 100644 --- a/test/allowed_families.cpp +++ b/test/allowed_families.cpp @@ -43,16 +43,22 @@ TEST_CASE("Testing families", "[data model]") // Wire up providers for each level g.provide("run_id_provider", provide_index, concurrency::unlimited) - .output_product("id"_in("run")); + .output_product(product_query{.creator = "dummy"_id, .layer = "run"_id, .suffix = "id"_id}); g.provide("subrun_id_provider", provide_index, concurrency::unlimited) - .output_product("id"_in("subrun")); + .output_product(product_query{.creator = "dummy"_id, .layer = "subrun"_id, .suffix = "id"_id}); g.provide("event_id_provider", provide_index, concurrency::unlimited) - .output_product("id"_in("event")); + .output_product(product_query{.creator = "dummy"_id, .layer = "event"_id, .suffix = "id"_id}); - g.observe("se", check_two_ids).input_family("id"_in("subrun"), "id"_in("event")); - g.observe("rs", check_two_ids).input_family("id"_in("run"), "id"_in("subrun")); + g.observe("se", check_two_ids) + .input_family(product_query{.creator = "dummy"_id, .layer = "subrun"_id, .suffix = "id"_id}, + product_query{.creator = "dummy"_id, .layer = "event"_id, .suffix = "id"_id}); + g.observe("rs", check_two_ids) + .input_family(product_query{.creator = "dummy"_id, .layer = "run"_id, .suffix = "id"_id}, + product_query{.creator = "dummy"_id, .layer = "subrun"_id, .suffix = "id"_id}); g.observe("rse", check_three_ids) - .input_family("id"_in("run"), "id"_in("subrun"), "id"_in("event")); + .input_family(product_query{.creator = "dummy"_id, .layer = "run"_id, .suffix = "id"_id}, + product_query{.creator = "dummy"_id, .layer = "subrun"_id, .suffix = "id"_id}, + product_query{.creator = "dummy"_id, .layer = "event"_id, .suffix = "id"_id}); g.execute(); CHECK(g.execution_counts("se") == 1ull); diff --git a/test/benchmarks/benchmark-04.jsonnet b/test/benchmarks/benchmark-04.jsonnet index 5d5a3702..49f4385e 100644 --- a/test/benchmarks/benchmark-04.jsonnet +++ b/test/benchmarks/benchmark-04.jsonnet @@ -2,13 +2,13 @@ driver: { cpp: 'generate_layers', layers: { - event: { total: 100000 } - } + event: { total: 100000 }, + }, }, sources: { provider: { - cpp: 'benchmarks_provider' - } + cpp: 'benchmarks_provider', + }, }, modules: { a_creator: { @@ -16,7 +16,11 @@ }, read_index: { cpp: 'read_index', - consumes: { product: 'a', layer: "event" } + consumes: { + creator: 'a_creator', + suffix: 'a', + layer: 'event', + }, }, }, } diff --git a/test/benchmarks/benchmark-05.jsonnet b/test/benchmarks/benchmark-05.jsonnet index 495995e1..9f5a7708 100644 --- a/test/benchmarks/benchmark-05.jsonnet +++ b/test/benchmarks/benchmark-05.jsonnet @@ -2,13 +2,13 @@ driver: { cpp: 'generate_layers', layers: { - event: { total: 100000 } - } + event: { total: 100000 }, + }, }, sources: { provider: { - cpp: 'benchmarks_provider' - } + cpp: 'benchmarks_provider', + }, }, modules: { b_creator: { @@ -21,7 +21,17 @@ }, d: { cpp: 'verify_difference', - expected: 0 + i: { + creator: 'b_creator', + layer: 'event', + suffix: 'b', + }, + j: { + creator: 'c_creator', + layer: 'event', + suffix: 'c', + }, + expected: 0, }, }, } diff --git a/test/benchmarks/benchmark-06.jsonnet b/test/benchmarks/benchmark-06.jsonnet index ee6c9a50..45680092 100644 --- a/test/benchmarks/benchmark-06.jsonnet +++ b/test/benchmarks/benchmark-06.jsonnet @@ -2,13 +2,13 @@ driver: { cpp: 'generate_layers', layers: { - event: { total: 100000 } - } + event: { total: 100000 }, + }, }, sources: { provider: { - cpp: 'benchmarks_provider' - } + cpp: 'benchmarks_provider', + }, }, modules: { a_creator: { @@ -16,12 +16,24 @@ }, b_creator: { cpp: 'plus_one', + input: { creator: 'a_creator', layer: 'event', suffix: 'a' }, }, c_creator: { cpp: 'plus_101', + input: { creator: 'a_creator', layer: 'event', suffix: 'a' }, }, d: { cpp: 'verify_difference', + i: { + creator: 'b_creator', + layer: 'event', + suffix: 'b', + }, + j: { + creator: 'c_creator', + layer: 'event', + suffix: 'c', + }, }, }, } diff --git a/test/benchmarks/benchmark-07.jsonnet b/test/benchmarks/benchmark-07.jsonnet index 3b6eef46..b7564d37 100644 --- a/test/benchmarks/benchmark-07.jsonnet +++ b/test/benchmarks/benchmark-07.jsonnet @@ -2,18 +2,18 @@ driver: { cpp: 'generate_layers', layers: { - event: { total: 100000 } - } + event: { total: 100000 }, + }, }, sources: { provider: { - cpp: 'benchmarks_provider' - } + cpp: 'benchmarks_provider', + }, }, modules: { even_filter: { cpp: 'accept_even_ids', - input: { product: 'id', layer: 'event' }, + input: { creator: 'input', suffix: 'id', layer: 'event' }, }, b_creator: { cpp: 'last_index', @@ -27,7 +27,17 @@ }, d: { cpp: 'verify_difference', - expected: 0 + i: { + creator: 'b_creator', + layer: 'event', + suffix: 'b', + }, + j: { + creator: 'c_creator', + layer: 'event', + suffix: 'c', + }, + expected: 0, }, }, } diff --git a/test/benchmarks/benchmark-08.jsonnet b/test/benchmarks/benchmark-08.jsonnet index a3f30291..75d7942a 100644 --- a/test/benchmarks/benchmark-08.jsonnet +++ b/test/benchmarks/benchmark-08.jsonnet @@ -4,13 +4,13 @@ local max_number = 100000; driver: { cpp: 'generate_layers', layers: { - event: { total: max_number } - } + event: { total: max_number }, + }, }, sources: { provider: { - cpp: 'benchmarks_provider' - } + cpp: 'benchmarks_provider', + }, }, modules: { a_creator: { @@ -19,17 +19,17 @@ local max_number = 100000; }, even_filter: { cpp: 'accept_even_numbers', - consumes: { product: 'a', layer: 'event' } + consumes: { creator: 'a_creator', suffix: 'a', layer: 'event' }, }, fibonacci_filter: { cpp: 'accept_fibonacci_numbers', - consumes: { product: 'a', layer: "event" }, + consumes: { creator: 'a_creator', suffix: 'a', layer: 'event' }, max_number: max_number, }, d: { cpp: 'verify_even_fibonacci_numbers', experimental_when: ['even_filter:accept_even_numbers', 'fibonacci_filter:accept'], - consumes: { product: 'a', layer: "event" }, + consumes: { creator: 'a_creator', suffix: 'a', layer: 'event' }, max_number: max_number, }, }, diff --git a/test/benchmarks/benchmark-09.jsonnet b/test/benchmarks/benchmark-09.jsonnet index b70f69cb..4997c557 100644 --- a/test/benchmarks/benchmark-09.jsonnet +++ b/test/benchmarks/benchmark-09.jsonnet @@ -2,29 +2,31 @@ driver: { cpp: 'generate_layers', layers: { - event: { total: 100000 } - } + event: { total: 100000 }, + }, }, sources: { provider: { - cpp: 'benchmarks_provider' - } + cpp: 'benchmarks_provider', + }, }, modules: { a_creator: { cpp: 'last_index', + input: { creator: 'a_creator', layer: 'event', suffix: 'a' }, }, b_creator: { cpp: 'plus_one', + input: { creator: 'a_creator', layer: 'event', suffix: 'a' }, }, even_filter: { cpp: 'accept_even_numbers', - consumes: { product: 'a', layer: "event" } + consumes: { creator: 'a_creator', suffix: 'a', layer: 'event' }, }, d: { cpp: 'read_index', experimental_when: ['even_filter:accept_even_numbers'], - consumes: { product: 'b', layer: "event" } + consumes: { creator: 'b_creator', suffix: 'b', layer: 'event' }, }, }, } diff --git a/test/benchmarks/benchmarks_provider.cpp b/test/benchmarks/benchmarks_provider.cpp index 126bd676..953ece8a 100644 --- a/test/benchmarks/benchmarks_provider.cpp +++ b/test/benchmarks/benchmarks_provider.cpp @@ -4,5 +4,5 @@ PHLEX_REGISTER_PROVIDERS(s) { using namespace phlex; s.provide("provide_id", [](data_cell_index const& id) { return id; }) - .output_product("id"_in("event")); + .output_product(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "id"_id}); } diff --git a/test/benchmarks/last_index.cpp b/test/benchmarks/last_index.cpp index bc1c6474..a39c6cda 100644 --- a/test/benchmarks/last_index.cpp +++ b/test/benchmarks/last_index.cpp @@ -10,6 +10,6 @@ namespace { PHLEX_REGISTER_ALGORITHMS(m, config) { m.transform("last_index", last_index, concurrency::unlimited) - .input_family("id"_in("event")) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "id"_id}) .output_products(config.get("produces", "a")); } diff --git a/test/benchmarks/plus_101.cpp b/test/benchmarks/plus_101.cpp index c5cbd128..f70462e7 100644 --- a/test/benchmarks/plus_101.cpp +++ b/test/benchmarks/plus_101.cpp @@ -6,9 +6,9 @@ namespace { int plus_101(int i) noexcept { return i + 101; } } -PHLEX_REGISTER_ALGORITHMS(m) +PHLEX_REGISTER_ALGORITHMS(m, config) { m.transform("plus_101", plus_101, concurrency::unlimited) - .input_family("a"_in("event")) + .input_family(config.get("input")) .output_products("c"); } diff --git a/test/benchmarks/plus_one.cpp b/test/benchmarks/plus_one.cpp index 8df74f41..6caf6797 100644 --- a/test/benchmarks/plus_one.cpp +++ b/test/benchmarks/plus_one.cpp @@ -6,9 +6,9 @@ namespace { int plus_one(int i) noexcept { return i + 1; } } -PHLEX_REGISTER_ALGORITHMS(m) +PHLEX_REGISTER_ALGORITHMS(m, config) { m.transform("plus_one", plus_one, concurrency::unlimited) - .input_family("a"_in("event")) + .input_family(config.get("input")) .output_products("b"); } diff --git a/test/benchmarks/read_id.cpp b/test/benchmarks/read_id.cpp index 4ed23775..43bb85c8 100644 --- a/test/benchmarks/read_id.cpp +++ b/test/benchmarks/read_id.cpp @@ -9,5 +9,6 @@ namespace { PHLEX_REGISTER_ALGORITHMS(m) { - m.observe("read_id", read_id, concurrency::unlimited).input_family("id"_in("event")); + m.observe("read_id", read_id, concurrency::unlimited) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "id"_id}); } diff --git a/test/benchmarks/verify_difference.cpp b/test/benchmarks/verify_difference.cpp index 81fc9317..fe2452a8 100644 --- a/test/benchmarks/verify_difference.cpp +++ b/test/benchmarks/verify_difference.cpp @@ -10,6 +10,5 @@ PHLEX_REGISTER_ALGORITHMS(m, config) "verify_difference", [expected = config.get("expected", 100)](int i, int j) { assert(j - i == expected); }, concurrency::unlimited) - .input_family(product_query{config.get("i", "b"), "event"}, - product_query{config.get("j", "c"), "event"}); + .input_family(config.get("i"), config.get("j")); } diff --git a/test/cached_execution.cpp b/test/cached_execution.cpp index 6ce4f075..20accd96 100644 --- a/test/cached_execution.cpp +++ b/test/cached_execution.cpp @@ -61,31 +61,37 @@ TEST_CASE("Cached function calls", "[data model]") // Register providers g.provide("provide_number", provide_number, concurrency::unlimited) - .output_product("number"_in("run")); + .output_product(product_query{.creator = "input"_id, .layer = "run"_id, .suffix = "number"_id}); g.provide("provide_another", provide_another, concurrency::unlimited) - .output_product("another"_in("subrun")); + .output_product( + product_query{.creator = "input"_id, .layer = "subrun"_id, .suffix = "another"_id}); g.provide("provide_still", provide_still, concurrency::unlimited) - .output_product("still"_in("event")); + .output_product( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "still"_id}); g.transform("A1", call_one, concurrency::unlimited) - .input_family("number"_in("run")) + .input_family(product_query{.creator = "input"_id, .layer = "run"_id, .suffix = "number"_id}) .output_products("one"); g.transform("A2", call_one, concurrency::unlimited) - .input_family("one"_in("run")) + .input_family(product_query{.creator = "A1"_id, .layer = "run"_id, .suffix = "one"_id}) .output_products("used_one"); g.transform("A3", call_one, concurrency::unlimited) - .input_family("used_one"_in("run")) + .input_family(product_query{.creator = "A2"_id, .layer = "run"_id, .suffix = "used_one"_id}) .output_products("done_one"); g.transform("B1", call_two, concurrency::unlimited) - .input_family("one"_in("run"), "another"_in("subrun")) + .input_family( + product_query{.creator = "A1"_id, .layer = "run"_id, .suffix = "one"_id}, + product_query{.creator = "input"_id, .layer = "subrun"_id, .suffix = "another"_id}) .output_products("two"); g.transform("B2", call_two, concurrency::unlimited) - .input_family("used_one"_in("run"), "two"_in("subrun")) + .input_family(product_query{.creator = "A2"_id, .layer = "run"_id, .suffix = "used_one"_id}, + product_query{.creator = "B1"_id, .layer = "subrun"_id, .suffix = "two"_id}) .output_products("used_two"); g.transform("C", call_two, concurrency::unlimited) - .input_family("used_two"_in("subrun"), "still"_in("event")) + .input_family(product_query{.creator = "B2"_id, .layer = "subrun"_id, .suffix = "used_two"_id}, + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "still"_id}) .output_products("three"); g.execute(); diff --git a/test/class_registration.cpp b/test/class_registration.cpp index 3a7bdf6b..4e8a0042 100644 --- a/test/class_registration.cpp +++ b/test/class_registration.cpp @@ -59,17 +59,22 @@ namespace { TEST_CASE("Call non-framework functions", "[programming model]") { - std::array const product_names{"number"_in("job"), "temperature"_in("job"), "name"_in("job")}; + std::array const product_names{ + product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "number"_id}, + product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "temperature"_id}, + product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "name"_id}}; std::array const oproduct_names{"onumber"s, "otemperature"s, "oname"s}; experimental::framework_graph g{data_cell_index::base_ptr()}; // Register providers for the input products g.provide("provide_number", provide_number, concurrency::unlimited) - .output_product("number"_in("job")); + .output_product(product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "number"_id}); g.provide("provide_temperature", provide_temperature, concurrency::unlimited) - .output_product("temperature"_in("job")); - g.provide("provide_name", provide_name, concurrency::unlimited).output_product("name"_in("job")); + .output_product( + product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "temperature"_id}); + g.provide("provide_name", provide_name, concurrency::unlimited) + .output_product(product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "name"_id}); auto glueball = g.make(); SECTION("No framework") diff --git a/test/configuration.cpp b/test/configuration.cpp index 43acfa32..e10280f9 100644 --- a/test/configuration.cpp +++ b/test/configuration.cpp @@ -32,15 +32,17 @@ TEST_CASE("Retrieve value that is a configuration object", "[config]") TEST_CASE("Retrieve product_query", "[config]") { boost::json::object input; - input["product"] = "tracks"; + input["creator"] = "tracks_alg"; + input["suffix"] = "tracks"; input["layer"] = "job"; boost::json::object malformed_input1; - malformed_input1["product"] = 16.; // Should be string + malformed_input1["creator"] = "test_alg"; + malformed_input1["suffix"] = 16.; // Should be string malformed_input1["layer"] = "job"; boost::json::object malformed_input2; - malformed_input2["product"] = "hits"; + malformed_input2["creator"] = "hits"; malformed_input2["level"] = "should be layer, not level"; boost::json::object underlying_config; @@ -50,10 +52,11 @@ TEST_CASE("Retrieve product_query", "[config]") configuration config{underlying_config}; auto input_query = config.get("input"); - CHECK(input_query == "tracks"_in("job")); + CHECK(input_query.match( + product_query{.creator = "tracks_alg"_id, .layer = "job"_id, .suffix = "tracks"_id})); CHECK_THROWS_WITH(config.get("malformed1"), ContainsSubstring("Error retrieving parameter 'malformed1'") && - ContainsSubstring("Error retrieving parameter 'product'")); + ContainsSubstring("Error retrieving parameter 'suffix'")); CHECK_THROWS_WITH(config.get("malformed2"), ContainsSubstring("Error retrieving parameter 'malformed2'") && ContainsSubstring("Error retrieving parameter 'layer'")); diff --git a/test/demo-giantdata/unfold_transform_fold.cpp b/test/demo-giantdata/unfold_transform_fold.cpp index 77cb2eab..1987815d 100644 --- a/test/demo-giantdata/unfold_transform_fold.cpp +++ b/test/demo-giantdata/unfold_transform_fold.cpp @@ -59,7 +59,7 @@ TEST_CASE("Unfold-transform-fold pipeline", "[concurrency][unfold][fold]") spill_index.parent()->number(), spill_index.number()); }) - .output_product("wgen"_in("spill")); + .output_product(product_query{.creator = "input"_id, .layer = "spill"_id, .suffix = "wgen"_id}); g.unfold( "WaveformGenerator", @@ -71,7 +71,7 @@ TEST_CASE("Unfold-transform-fold pipeline", "[concurrency][unfold][fold]") }, concurrency::unlimited, "APA") - .input_family("wgen"_in("spill")) + .input_family(product_query{.creator = "input"_id, .layer = "spill"_id, .suffix = "wgen"_id}) .output_products("waves_in_apa"); // Add the transform node to the graph @@ -80,7 +80,8 @@ TEST_CASE("Unfold-transform-fold pipeline", "[concurrency][unfold][fold]") }; g.transform("clamp_node", wrapped_user_function, concurrency::unlimited) - .input_family("waves_in_apa"_in("APA")) + .input_family(product_query{ + .creator = "WaveformGenerator"_id, .layer = "APA"_id, .suffix = "waves_in_apa"_id}) .output_products("clamped_waves"); // Add the fold node with instrumentation to detect pipelined execution @@ -97,7 +98,8 @@ TEST_CASE("Unfold-transform-fold pipeline", "[concurrency][unfold][fold]") }, concurrency::unlimited, "spill") - .input_family("clamped_waves"_in("APA")) + .input_family( + product_query{.creator = "clamp_node"_id, .layer = "APA"_id, .suffix = "clamped_waves"_id}) .output_products("summed_waveforms"); // Execute the graph diff --git a/test/different_hierarchies.cpp b/test/different_hierarchies.cpp index f06161d5..f4bca6ee 100644 --- a/test/different_hierarchies.cpp +++ b/test/different_hierarchies.cpp @@ -66,22 +66,25 @@ TEST_CASE("Different hierarchies used with fold", "[graph]") // Register provider g.provide("provide_number", provide_number, concurrency::unlimited) - .output_product("number"_in("event")); + .output_product( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "number"_id}); g.fold("run_add", add, concurrency::unlimited, "run", 0u) - .input_family("number"_in("event")) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "number"_id}) .output_products("run_sum"); g.fold("job_add", add, concurrency::unlimited) - .input_family("number"_in("event")) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "number"_id}) .output_products("job_sum"); g.observe("verify_run_sum", [](unsigned int actual) { CHECK(actual == 10u); }) - .input_family("run_sum"_in("run")); + .input_family( + product_query{.creator = "run_add"_id, .layer = "run"_id, .suffix = "run_sum"_id}); g.observe("verify_job_sum", [](unsigned int actual) { CHECK(actual == 20u + 45u); // 20u from nested events, 45u from top-level events }) - .input_family("job_sum"_in("job")); + .input_family( + product_query{.creator = "job_add"_id, .layer = "job"_id, .suffix = "job_sum"_id}); g.execute(); diff --git a/test/filter.cpp b/test/filter.cpp index 4bafcf7d..4804ece1 100644 --- a/test/filter.cpp +++ b/test/filter.cpp @@ -89,16 +89,19 @@ namespace { TEST_CASE("Two predicates", "[filtering]") { experimental::framework_graph g{source{10u}}; - g.provide("provide_num", give_me_nums, concurrency::unlimited).output_product("num"_in("event")); - g.predicate("evens_only", evens_only, concurrency::unlimited).input_family("num"_in("event")); - g.predicate("odds_only", odds_only, concurrency::unlimited).input_family("num"_in("event")); + g.provide("provide_num", give_me_nums, concurrency::unlimited) + .output_product(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}); + g.predicate("evens_only", evens_only, concurrency::unlimited) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}); + g.predicate("odds_only", odds_only, concurrency::unlimited) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}); g.make(20u) .observe("add_evens", &sum_numbers::add, concurrency::unlimited) - .input_family("num"_in("event")) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}) .experimental_when("evens_only"); g.make(25u) .observe("add_odds", &sum_numbers::add, concurrency::unlimited) - .input_family("num"_in("event")) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}) .experimental_when("odds_only"); g.execute(); @@ -110,14 +113,16 @@ TEST_CASE("Two predicates", "[filtering]") TEST_CASE("Two predicates in series", "[filtering]") { experimental::framework_graph g{source{10u}}; - g.provide("provide_num", give_me_nums, concurrency::unlimited).output_product("num"_in("event")); - g.predicate("evens_only", evens_only, concurrency::unlimited).input_family("num"_in("event")); + g.provide("provide_num", give_me_nums, concurrency::unlimited) + .output_product(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}); + g.predicate("evens_only", evens_only, concurrency::unlimited) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}); g.predicate("odds_only", odds_only, concurrency::unlimited) - .input_family("num"_in("event")) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}) .experimental_when("evens_only"); g.make(0u) .observe("add", &sum_numbers::add, concurrency::unlimited) - .input_family("num"_in("event")) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}) .experimental_when("odds_only"); g.execute(); @@ -128,12 +133,15 @@ TEST_CASE("Two predicates in series", "[filtering]") TEST_CASE("Two predicates in parallel", "[filtering]") { experimental::framework_graph g{source{10u}}; - g.provide("provide_num", give_me_nums, concurrency::unlimited).output_product("num"_in("event")); - g.predicate("evens_only", evens_only, concurrency::unlimited).input_family("num"_in("event")); - g.predicate("odds_only", odds_only, concurrency::unlimited).input_family("num"_in("event")); + g.provide("provide_num", give_me_nums, concurrency::unlimited) + .output_product(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}); + g.predicate("evens_only", evens_only, concurrency::unlimited) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}); + g.predicate("odds_only", odds_only, concurrency::unlimited) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}); g.make(0u) .observe("add", &sum_numbers::add, concurrency::unlimited) - .input_family("num"_in("event")) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}) .experimental_when("odds_only", "evens_only"); g.execute(); @@ -153,11 +161,12 @@ TEST_CASE("Three predicates in parallel", "[filtering]") {.name = "exclude_gt_8", .begin = 8, .end = -1u}}; experimental::framework_graph g{source{10u}}; - g.provide("provide_num", give_me_nums, concurrency::unlimited).output_product("num"_in("event")); + g.provide("provide_num", give_me_nums, concurrency::unlimited) + .output_product(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}); for (auto const& [name, b, e] : configs) { g.make(b, e) .predicate(name, ¬_in_range::eval, concurrency::unlimited) - .input_family("num"_in("event")); + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}); } std::vector const predicate_names{ @@ -165,7 +174,7 @@ TEST_CASE("Three predicates in parallel", "[filtering]") auto const expected_numbers = {4u, 5u, 7u}; g.make(expected_numbers) .observe("collect", &collect_numbers::collect, concurrency::unlimited) - .input_family("num"_in("event")) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}) .experimental_when(predicate_names); g.execute(); @@ -176,19 +185,29 @@ TEST_CASE("Three predicates in parallel", "[filtering]") TEST_CASE("Two predicates in parallel (each with multiple arguments)", "[filtering]") { experimental::framework_graph g{source{10u}}; - g.provide("provide_num", give_me_nums, concurrency::unlimited).output_product("num"_in("event")); + g.provide("provide_num", give_me_nums, concurrency::unlimited) + .output_product(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}); g.provide("provide_other_num", give_me_other_nums, concurrency::unlimited) - .output_product("other_num"_in("event")); - g.predicate("evens_only", evens_only, concurrency::unlimited).input_family("num"_in("event")); - g.predicate("odds_only", odds_only, concurrency::unlimited).input_family("num"_in("event")); + .output_product( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "other_num"_id}); + g.predicate("evens_only", evens_only, concurrency::unlimited) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}); + g.predicate("odds_only", odds_only, concurrency::unlimited) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}); g.make(5 * 100) .observe("check_evens", &check_multiple_numbers::add_difference, concurrency::unlimited) - .input_family("num"_in("event"), "other_num"_in("event")) // <= Note input order + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}, + product_query{.creator = "input"_id, + .layer = "event"_id, + .suffix = "other_num"_id}) // <= Note input order .experimental_when("evens_only"); g.make(-5 * 100) .observe("check_odds", &check_multiple_numbers::add_difference, concurrency::unlimited) - .input_family("other_num"_in("event"), "num"_in("event")) // <= Note input order + .input_family( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "other_num"_id}, + product_query{ + .creator = "input"_id, .layer = "event"_id, .suffix = "num"_id}) // <= Note input order .experimental_when("odds_only"); g.execute(); diff --git a/test/filter_impl.cpp b/test/filter_impl.cpp index 27920b38..90daa640 100644 --- a/test/filter_impl.cpp +++ b/test/filter_impl.cpp @@ -45,8 +45,10 @@ TEST_CASE("Filter decision", "[filtering]") TEST_CASE("Filter data map", "[filtering]") { - using phlex::operator""_in; - std::vector const data_products_to_cache{"a"_in("spill"), "b"_in("spill")}; + using phlex::product_query; + std::vector const data_products_to_cache{ + product_query{.creator = "input"_id, .layer = "spill"_id, .suffix = "a"_id}, + product_query{.creator = "input"_id, .layer = "spill"_id, .suffix = "b"_id}}; data_map data{data_products_to_cache}; // Stores with the data products "a" and "b" diff --git a/test/fold.cpp b/test/fold.cpp index 62fa4b3b..31cca53c 100644 --- a/test/fold.cpp +++ b/test/fold.cpp @@ -53,25 +53,29 @@ TEST_CASE("Different data layers of fold", "[graph]") experimental::framework_graph g{driver_for_test(gen)}; g.provide("provide_number", provide_number, concurrency::unlimited) - .output_product("number"_in("event")); + .output_product( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "number"_id}); g.fold("run_add", add, concurrency::unlimited, "run") - .input_family("number"_in("event")) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "number"_id}) .output_products("run_sum"); g.fold("job_add", add, concurrency::unlimited) - .input_family("number"_in("event")) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "number"_id}) .output_products("job_sum"); g.fold("two_layer_job_add", add, concurrency::unlimited) - .input_family("run_sum"_in("run")) + .input_family(product_query{.creator = "run_add"_id, .layer = "run"_id, .suffix = "run_sum"_id}) .output_products("two_layer_job_sum"); g.observe("verify_run_sum", [](unsigned int actual) { CHECK(actual == 10u); }) - .input_family("run_sum"_in("run")); + .input_family( + product_query{.creator = "run_add"_id, .layer = "run"_id, .suffix = "run_sum"_id}); g.observe("verify_two_layer_job_sum", [](unsigned int actual) { CHECK(actual == 20u); }) - .input_family("two_layer_job_sum"_in("job")); + .input_family(product_query{ + .creator = "two_layer_job_add"_id, .layer = "job"_id, .suffix = "two_layer_job_sum"_id}); g.observe("verify_job_sum", [](unsigned int actual) { CHECK(actual == 20u); }) - .input_family("job_sum"_in("job")); + .input_family( + product_query{.creator = "job_add"_id, .layer = "job"_id, .suffix = "job_sum"_id}); g.execute(); diff --git a/test/framework_graph.cpp b/test/framework_graph.cpp index beb879ee..6a38b775 100644 --- a/test/framework_graph.cpp +++ b/test/framework_graph.cpp @@ -29,10 +29,11 @@ TEST_CASE("Make progress with one thread", "[graph]") "provide_number", [](data_cell_index const& index) -> unsigned int { return index.number(); }, concurrency::unlimited) - .output_product("number"_in("spill")); + .output_product( + product_query{.creator = "input"_id, .layer = "spill"_id, .suffix = "number"_id}); g.observe( "observe_number", [](unsigned int const /*number*/) {}, concurrency::unlimited) - .input_family("number"_in("spill")); + .input_family(product_query{.creator = "input"_id, .layer = "spill"_id, .suffix = "number"_id}); g.execute(); CHECK(gen.emitted_cells("/job/spill") == 1000); diff --git a/test/function_registration.cpp b/test/function_registration.cpp index 552560d5..4df01d46 100644 --- a/test/function_registration.cpp +++ b/test/function_registration.cpp @@ -54,7 +54,10 @@ namespace { TEST_CASE("Call non-framework functions", "[programming model]") { - std::array const product_names{"number"_in("job"), "temperature"_in("job"), "name"_in("job")}; + std::array const product_names{ + product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "number"_id}, + product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "temperature"_id}, + product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "name"_id}}; std::array const oproduct_names = {"onumber"s, "otemperature"s, "oname"s}; std::array const result{"result"s}; @@ -62,10 +65,12 @@ TEST_CASE("Call non-framework functions", "[programming model]") // Register providers g.provide("provide_number", provide_number, concurrency::unlimited) - .output_product("number"_in("job")); + .output_product(product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "number"_id}); g.provide("provide_temperature", provide_temperature, concurrency::unlimited) - .output_product("temperature"_in("job")); - g.provide("provide_name", provide_name, concurrency::unlimited).output_product("name"_in("job")); + .output_product( + product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "temperature"_id}); + g.provide("provide_name", provide_name, concurrency::unlimited) + .output_product(product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "name"_id}); SECTION("No framework") { diff --git a/test/hierarchical_nodes.cpp b/test/hierarchical_nodes.cpp index 457aa4e8..57edac59 100644 --- a/test/hierarchical_nodes.cpp +++ b/test/hierarchical_nodes.cpp @@ -93,7 +93,7 @@ TEST_CASE("Hierarchical nodes", "[graph]") spdlog::info("Providing time for {}", index.to_string()); return std::time(nullptr); }) - .output_product("time"_in("run")); + .output_product(product_query{.creator = "input"_id, .layer = "run"_id, .suffix = "time"_id}); g.provide("provide_number", [](data_cell_index const& index) -> unsigned int { @@ -101,26 +101,30 @@ TEST_CASE("Hierarchical nodes", "[graph]") auto const run_number = index.parent()->number(); return event_number + run_number; }) - .output_product("number"_in("event")); + .output_product( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "number"_id}); g.transform("get_the_time", strtime, concurrency::unlimited) - .input_family("time"_in("run")) + .input_family(product_query{.creator = "input"_id, .layer = "run"_id, .suffix = "time"_id}) .experimental_when() .output_products("strtime"); g.transform("square", square, concurrency::unlimited) - .input_family("number"_in("event")) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "number"_id}) .output_products("squared_number"); g.fold("add", add, concurrency::unlimited, "run", 15u) - .input_family("squared_number"_in("event")) + .input_family( + product_query{.creator = "square"_id, .layer = "event"_id, .suffix = "squared_number"_id}) .experimental_when() .output_products("added_data"); g.transform("scale", scale, concurrency::unlimited) - .input_family("added_data"_in("run")) + .input_family(product_query{.creator = "add"_id, .layer = "run"_id, .suffix = "added_data"_id}) .output_products("result"); g.observe("print_result", print_result, concurrency::unlimited) - .input_family("result"_in("run"), "strtime"_in("run")); + .input_family( + product_query{.creator = "scale"_id, .layer = "run"_id, .suffix = "result"_id}, + product_query{.creator = "get_the_time"_id, .layer = "run"_id, .suffix = "strtime"_id}); g.make() .output("save", &experimental::test::products_for_output::save) diff --git a/test/max-parallelism/check_parallelism.cpp b/test/max-parallelism/check_parallelism.cpp index 26cd719b..f57766be 100644 --- a/test/max-parallelism/check_parallelism.cpp +++ b/test/max-parallelism/check_parallelism.cpp @@ -15,5 +15,6 @@ PHLEX_REGISTER_ALGORITHMS(m, config) [expected = config.get("expected_parallelism")](std::size_t actual) { assert(actual == expected); }) - .input_family("max_parallelism"_in("job")); + .input_family( + product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "max_parallelism"_id}); } diff --git a/test/max-parallelism/provide_parallelism.cpp b/test/max-parallelism/provide_parallelism.cpp index c41f1381..6aad9ca0 100644 --- a/test/max-parallelism/provide_parallelism.cpp +++ b/test/max-parallelism/provide_parallelism.cpp @@ -7,5 +7,6 @@ PHLEX_REGISTER_PROVIDERS(s) s.provide( "provide_max_parallelism", [](data_cell_index const&) { return experimental::max_allowed_parallelism::active_value(); }) - .output_product("max_parallelism"_in("job")); + .output_product( + product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "max_parallelism"_id}); } diff --git a/test/memory-checks/many_events.cpp b/test/memory-checks/many_events.cpp index c6e4fff4..20fec2ee 100644 --- a/test/memory-checks/many_events.cpp +++ b/test/memory-checks/many_events.cpp @@ -19,9 +19,10 @@ int main() experimental::framework_graph g{driver_for_test(gen)}; g.provide("provide_number", [](data_cell_index const& id) -> unsigned { return id.number(); }) - .output_product("number"_in("event")); + .output_product( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "number"_id}); g.transform("pass_on", pass_on, concurrency::unlimited) - .input_family("number"_in("event")) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "number"_id}) .output_products("different"); g.execute(); } diff --git a/test/mock-workflow/G4Stage1.libsonnet b/test/mock-workflow/G4Stage1.libsonnet index df22de14..4df6a8d6 100644 --- a/test/mock-workflow/G4Stage1.libsonnet +++ b/test/mock-workflow/G4Stage1.libsonnet @@ -1,11 +1,11 @@ -local ev = import "event_product.libsonnet"; local generators = import 'SinglesGen.libsonnet'; +local ev = import 'event_product.libsonnet'; { largeant: { cpp: 'largeant', - duration_usec: 156, # Typical: 15662051 - inputs: [ev.event_product(f + "/MCTruths") for f in std.objectFields(generators)], - outputs: ["ParticleAncestryMap", "Assns", "SimEnergyDeposits", "AuxDetHits", "MCParticles"], - } + duration_usec: 156, // Typical: 15662051 + inputs: [ev.creator_event_product(f, 'MCTruths') for f in std.objectFields(generators)], + outputs: ['ParticleAncestryMap', 'Assns', 'SimEnergyDeposits', 'AuxDetHits', 'MCParticles'], + }, } diff --git a/test/mock-workflow/G4Stage2.libsonnet b/test/mock-workflow/G4Stage2.libsonnet index 535e90a7..73f73fb6 100644 --- a/test/mock-workflow/G4Stage2.libsonnet +++ b/test/mock-workflow/G4Stage2.libsonnet @@ -1,17 +1,17 @@ -local ev = import "event_product.libsonnet"; local g4stage1 = import 'G4Stage1.libsonnet'; +local ev = import 'event_product.libsonnet'; { IonAndScint: { cpp: 'ion_and_scint', - duration_usec: 546, # Typical: 5457973 - inputs: [ev.event_product(f + "/SimEnergyDeposits") for f in std.objectFields(g4stage1)], - outputs: ["SimEnergyDeposits", "SimEnergyDeposits_priorSCE"], + duration_usec: 546, // Typical: 5457973 + inputs: [ev.creator_event_product(f, 'SimEnergyDeposits') for f in std.objectFields(g4stage1)], + outputs: ['SimEnergyDeposits', 'SimEnergyDeposits_priorSCE'], }, PDFastSim: { cpp: 'pd_fast_sim', - duration_usec: 69, # Typical: 69681950 - inputs: [ev.event_product('SimEnergyDeposits_priorSCE')], + duration_usec: 69, // Typical: 69681950 + inputs: [ev.creator_event_product('IonAndScint', 'SimEnergyDeposits_priorSCE')], outputs: ['SimPhotonLites', 'OpDetBacktrackerRecords'], - } + }, } diff --git a/test/mock-workflow/event_product.libsonnet b/test/mock-workflow/event_product.libsonnet index a3f0cfc4..9cda3758 100644 --- a/test/mock-workflow/event_product.libsonnet +++ b/test/mock-workflow/event_product.libsonnet @@ -1,7 +1,15 @@ { event_product(product):: { - product: product, - layer: "event" - } + creator: 'input', + suffix: product, + layer: 'event', + }, + + creator_event_product(creator, product):: + { + creator: creator, + suffix: product, + layer: 'event', + }, } diff --git a/test/mock-workflow/id_provider.cpp b/test/mock-workflow/id_provider.cpp index 126bd676..953ece8a 100644 --- a/test/mock-workflow/id_provider.cpp +++ b/test/mock-workflow/id_provider.cpp @@ -4,5 +4,5 @@ PHLEX_REGISTER_PROVIDERS(s) { using namespace phlex; s.provide("provide_id", [](data_cell_index const& id) { return id; }) - .output_product("id"_in("event")); + .output_product(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "id"_id}); } diff --git a/test/multiple_function_registration.cpp b/test/multiple_function_registration.cpp index fa338c70..c4d80909 100644 --- a/test/multiple_function_registration.cpp +++ b/test/multiple_function_registration.cpp @@ -45,41 +45,51 @@ TEST_CASE("Call multiple functions", "[programming model]") g.provide("provide_numbers", [](data_cell_index const&) -> std::vector { return {0, 1, 2, 3, 4}; }) - .output_product("numbers"_in("job")); + .output_product( + product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "numbers"_id}); g.provide("provide_offset", [](data_cell_index const&) -> unsigned { return 6u; }) - .output_product("offset"_in("job")); + .output_product(product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "offset"_id}); SECTION("All free functions") { g.transform("square_numbers", square_numbers, concurrency::unlimited) - .input_family("numbers"_in("job")) + .input_family(product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "numbers"_id}) .output_products("squared_numbers"); g.transform("sum_numbers", sum_numbers, concurrency::unlimited) - .input_family("squared_numbers"_in("job")) + .input_family(product_query{ + .creator = "square_numbers"_id, .layer = "job"_id, .suffix = "squared_numbers"_id}) .output_products("summed_numbers"); - g.transform("sqrt_sum_numbers", sqrt_sum_numbers, concurrency::unlimited) - .input_family("summed_numbers"_in("job"), "offset"_in("job")) + g.transform("sqrt_sum", sqrt_sum_numbers, concurrency::unlimited) + .input_family(product_query{.creator = "sum_numbers"_id, + .layer = "job"_id, + .suffix = "summed_numbers"_id}, + product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "offset"_id}) .output_products("result"); } SECTION("Transforms, one from a class") { g.transform("square_numbers", square_numbers, concurrency::unlimited) - .input_family("numbers"_in("job")) + .input_family(product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "numbers"_id}) .output_products("squared_numbers"); g.transform("sum_numbers", sum_numbers, concurrency::unlimited) - .input_family("squared_numbers"_in("job")) + .input_family(product_query{ + .creator = "square_numbers"_id, .layer = "job"_id, .suffix = "squared_numbers"_id}) .output_products("summed_numbers"); g.make() .transform("sqrt_sum", &A::sqrt_sum, concurrency::unlimited) - .input_family("summed_numbers"_in("job"), "offset"_in("job")) + .input_family(product_query{.creator = "sum_numbers"_id, + .layer = "job"_id, + .suffix = "summed_numbers"_id}, + product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "offset"_id}) .output_products("result"); } // The following is invoked for *each* section above g.observe("verify_result", [](double actual) { assert(actual == 6.); }) - .input_family("result"_in("job")); + .input_family( + product_query{.creator = "sqrt_sum"_id, .layer = "job"_id, .suffix = "result"_id}); g.execute(); } diff --git a/test/plugins/ij_source.cpp b/test/plugins/ij_source.cpp index 0eec1c18..9c02ed37 100644 --- a/test/plugins/ij_source.cpp +++ b/test/plugins/ij_source.cpp @@ -5,7 +5,7 @@ using namespace phlex; PHLEX_REGISTER_PROVIDERS(s) { s.provide("provide_i", [](data_cell_index const& id) -> int { return id.number(); }) - .output_product("i"_in("event")); + .output_product(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "i"_id}); s.provide("provide_j", [](data_cell_index const& id) -> int { return -id.number(); }) - .output_product("j"_in("event")); + .output_product(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "j"_id}); } diff --git a/test/plugins/module.cpp b/test/plugins/module.cpp index db189077..e37f10f1 100644 --- a/test/plugins/module.cpp +++ b/test/plugins/module.cpp @@ -8,9 +8,10 @@ using namespace phlex; PHLEX_REGISTER_ALGORITHMS(m) { m.transform("add", test::add, concurrency::unlimited) - .input_family("i"_in("event"), "j"_in("event")) + .input_family(product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "i"_id}, + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "j"_id}) .output_products("sum"); m.observe( "verify", [](int actual) { assert(actual == 0); }, concurrency::unlimited) - .input_family("sum"_in("event")); + .input_family(product_query{.creator = "add"_id, .layer = "event"_id, .suffix = "sum"_id}); } diff --git a/test/product_query.cpp b/test/product_query.cpp index ade872d6..47883c59 100644 --- a/test/product_query.cpp +++ b/test/product_query.cpp @@ -7,15 +7,18 @@ using namespace phlex; TEST_CASE("Empty specifications", "[data model]") { - CHECK_THROWS_WITH(""_in, - Catch::Matchers::ContainsSubstring("Cannot specify product with empty name.")); CHECK_THROWS_WITH( - "product"_in(""), + (product_query{.creator = ""_id, .layer = "layer"_id}), + Catch::Matchers::ContainsSubstring("Cannot specify product with empty creator name.")); + CHECK_THROWS_WITH( + (product_query{.creator = "creator"_id, .layer = ""_id}), Catch::Matchers::ContainsSubstring("Cannot specify the empty string as a data layer.")); } TEST_CASE("Product name with data layer", "[data model]") { - product_query label{"product", {"event"}}; - CHECK(label == "product"_in("event")); + product_query label({.creator = "creator"_id, .layer = "event"_id, .suffix = "product"_id}); + CHECK(label.creator == "creator"_id); + CHECK(label.layer == "event"_id); + CHECK(label.suffix == "product"_idq); } diff --git a/test/provider_test.cpp b/test/provider_test.cpp index d8e6281d..58b1771f 100644 --- a/test/provider_test.cpp +++ b/test/provider_test.cpp @@ -39,10 +39,12 @@ TEST_CASE("provider_test") experimental::framework_graph g{driver_for_test(gen)}; g.provide("my_name_here", give_me_vertices, concurrency::unlimited) - .output_product("happy_vertices"_in("spill")); + .output_product( + product_query{.creator = "input"_id, .layer = "spill"_id, .suffix = "happy_vertices"_id}); g.transform("passer", pass_on, concurrency::unlimited) - .input_family("happy_vertices"_in("spill")) + .input_family( + product_query{.creator = "input"_id, .layer = "spill"_id, .suffix = "happy_vertices"_id}) .output_products("vertex_data"); g.execute(); diff --git a/test/python/source.cpp b/test/python/source.cpp index 2a6aac8f..35c65af4 100644 --- a/test/python/source.cpp +++ b/test/python/source.cpp @@ -6,7 +6,7 @@ using namespace phlex; PHLEX_REGISTER_PROVIDERS(s) { s.provide("provide_i", [](data_cell_index const& id) -> int { return id.number(); }) - .output_product("i"_in("job")); + .output_product(product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "i"_id}); s.provide("provide_j", [](data_cell_index const& id) -> int { return -id.number() + 1; }) - .output_product("j"_in("job")); + .output_product(product_query{.creator = "input"_id, .layer = "job"_id, .suffix = "j"_id}); } diff --git a/test/type_distinction.cpp b/test/type_distinction.cpp index c9a71ef3..6031825a 100644 --- a/test/type_distinction.cpp +++ b/test/type_distinction.cpp @@ -57,55 +57,73 @@ TEST_CASE("Distinguish products with same name and different types", "[programmi // Register providers g.provide("provide_numbers", provide_numbers, concurrency::unlimited) - .output_product("numbers"_in("event")); + .output_product( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "numbers"_id}); g.provide("provide_length", provide_length, concurrency::unlimited) - .output_product("length"_in("event")); + .output_product( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "length"_id}); - SECTION("Duplicate product name but differ in producer name") + SECTION("Duplicate product name but differ in creator name") { g.observe("starter", [](int num) { spdlog::info("Received {}", num); }) - .input_family("numbers"_in("event")); + .input_family( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "numbers"_id}); g.transform("triple_numbers", triple, concurrency::unlimited) - .input_family("numbers"_in("event")) + .input_family( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "numbers"_id}) .output_products("tripled"); spdlog::info("Registered tripled"); g.transform("expand_orig", expand, concurrency::unlimited) - .input_family("numbers"_in("event"), "length"_in("event")) + .input_family( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "numbers"_id}, + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "length"_id}) .output_products("expanded_one"); spdlog::info("Registered expanded_one"); g.transform("expand_triples", expand, concurrency::unlimited) - .input_family("tripled"_in("event"), "length"_in("event")) + .input_family( + product_query{.creator = "triple_numbers"_id, .layer = "event"_id, .suffix = "tripled"_id}, + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "length"_id}) .output_products("expanded_three"); spdlog::info("Registered expanded_three"); g.transform("add_nums", add_numbers, concurrency::unlimited) - .input_family("numbers"_in("event"), "tripled"_in("event")) + .input_family( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "numbers"_id}, + product_query{.creator = "triple_numbers"_id, .layer = "event"_id, .suffix = "tripled"_id}) .output_products("sums"); spdlog::info("Registered sums"); g.transform("add_vect", add_vectors, concurrency::unlimited) - .input_family("expanded_one"_in("event"), "expanded_three"_in("event")) + .input_family( + product_query{ + .creator = "expand_orig"_id, .layer = "event"_id, .suffix = "expanded_one"_id}, + product_query{ + .creator = "expand_triples"_id, .layer = "event"_id, .suffix = "expanded_three"_id}) .output_products("sums"); - g.transform("test_add_num", triple, concurrency::unlimited) - .input_family("sums"_in("event")) + g.transform("extract_result", triple, concurrency::unlimited) + .input_family( + product_query{.creator = "add_nums"_id, .layer = "event"_id, .suffix = "sums"_id}) .output_products("result"); spdlog::info("Registered result"); } - SECTION("Duplicate product name and producer, differ only in type") + SECTION("Duplicate product name and creator, differ only in type") { g.transform("square", square, concurrency::unlimited) - .input_family("numbers"_in("event")) + .input_family( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "numbers"_id}) .output_products("square_result", "square_result"); g.transform("extract_result", id, concurrency::unlimited) - .input_family("square_result"_in("event")) + .input_family( + product_query{.creator = "square"_id, .layer = "event"_id, .suffix = "square_result"_id}) .output_products("result"); } g.observe("print_result", [](int res) { spdlog::info("Result: {}", res); }) - .input_family("result"_in("event")); + .input_family( + product_query{.creator = "extract_result"_id, .layer = "event"_id, .suffix = "result"_id}); spdlog::info("Registered observe"); g.execute(); spdlog::info("Executed"); diff --git a/test/unfold.cpp b/test/unfold.cpp index faee73fd..dd328310 100644 --- a/test/unfold.cpp +++ b/test/unfold.cpp @@ -97,30 +97,38 @@ TEST_CASE("Splitting the processing", "[graph]") experimental::framework_graph g{driver_for_test(gen)}; g.provide("provide_max_number", provide_max_number, concurrency::unlimited) - .output_product("max_number"_in("event")); + .output_product( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "max_number"_id}); g.provide("provide_ten_numbers", provide_ten_numbers, concurrency::unlimited) - .output_product("ten_numbers"_in("event")); + .output_product( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "ten_numbers"_id}); g.unfold("iota", &iota::predicate, &iota::unfold, concurrency::unlimited, "lower1") - .input_family("max_number"_in("event")) + .input_family( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "max_number"_id}) .output_products("new_number"); g.fold("add", add, concurrency::unlimited, "event") - .input_family("new_number"_in("lower1")) + .input_family( + product_query{.creator = "iota"_id, .layer = "lower1"_id, .suffix = "new_number"_id}) .output_products("sum1"); - g.observe("check_sum", check_sum, concurrency::unlimited).input_family("sum1"_in("event")); + g.observe("check_sum", check_sum, concurrency::unlimited) + .input_family(product_query{.creator = "add"_id, .layer = "event"_id, .suffix = "sum1"_id}); g.unfold("iterate_through", &iterate_through::predicate, &iterate_through::unfold, concurrency::unlimited, "lower2") - .input_family("ten_numbers"_in("event")) + .input_family( + product_query{.creator = "input"_id, .layer = "event"_id, .suffix = "ten_numbers"_id}) .output_products("each_number"); g.fold("add_numbers", add_numbers, concurrency::unlimited, "event") - .input_family("each_number"_in("lower2")) + .input_family(product_query{ + .creator = "iterate_through"_id, .layer = "lower2"_id, .suffix = "each_number"_id}) .output_products("sum2"); g.observe("check_sum_same", check_sum_same, concurrency::unlimited) - .input_family("sum2"_in("event")); + .input_family( + product_query{.creator = "add_numbers"_id, .layer = "event"_id, .suffix = "sum2"_id}); g.make().output( "save", &experimental::test::products_for_output::save, concurrency::serial); diff --git a/test/vector_of_abstract_types.cpp b/test/vector_of_abstract_types.cpp index 6da3234d..a3731513 100644 --- a/test/vector_of_abstract_types.cpp +++ b/test/vector_of_abstract_types.cpp @@ -44,11 +44,15 @@ TEST_CASE("Test vector of abstract types") experimental::framework_graph g{driver_for_test(gen)}; g.provide("provide_thing", [](data_cell_index const&) { return make_derived_as_abstract(); }) - .output_product("thing"_in("event")); - g.transform("read_thing", read_abstract).input_family("thing"_in("event")).output_products("sum"); + .output_product( + product_query{.creator = "dummy"_id, .layer = "event"_id, .suffix = "thing"_id}); + g.transform("read_thing", read_abstract) + .input_family(product_query{.creator = "dummy"_id, .layer = "event"_id, .suffix = "thing"_id}) + .output_products("sum"); g.observe( "verify_sum", [](int sum) { CHECK(sum == 3); }, concurrency::serial) - .input_family("sum"_in("event")); + .input_family( + product_query{.creator = "read_thing"_id, .layer = "event"_id, .suffix = "sum"_id}); g.execute(); CHECK(g.execution_counts("read_thing") == 1);