diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e420734b..dad564236 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,7 +63,6 @@ option(ENABLE_TSAN "Enable Thread Sanitizer" OFF) option(ENABLE_ASAN "Enable Address Sanitizer" OFF) option(PHLEX_USE_FORM "Enable experimental integration with FORM" OFF) option(ENABLE_COVERAGE "Enable code coverage instrumentation" OFF) -option(ENABLE_CLANG_TIDY "Enable clang-tidy checks during build" OFF) add_compile_options( -Wall @@ -163,22 +162,6 @@ if(ENABLE_COVERAGE) endif() endif() -# Configure clang-tidy integration -find_program(CLANG_TIDY_EXECUTABLE NAMES clang-tidy-20 clang-tidy) - -if(ENABLE_CLANG_TIDY) - if(CLANG_TIDY_EXECUTABLE) - message(STATUS "Found clang-tidy: ${CLANG_TIDY_EXECUTABLE}") - set( - CMAKE_CXX_CLANG_TIDY - ${CLANG_TIDY_EXECUTABLE} - --config-file=${CMAKE_SOURCE_DIR}/.clang-tidy - ) - else() - message(WARNING "clang-tidy not found, disabling clang-tidy checks") - endif() -endif() - if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Build type" FORCE) endif() @@ -202,10 +185,4 @@ if(BUILD_TESTING) endif() endif() -# Report clang-tidy availability -if(CLANG_TIDY_EXECUTABLE) - message(STATUS "Clang-tidy available: ${CLANG_TIDY_EXECUTABLE}") - message(STATUS "Use -DCMAKE_CXX_CLANG_TIDY=clang-tidy to enable automatic checks during build") -endif() - cet_cmake_config() diff --git a/phlex/core/declared_fold.hpp b/phlex/core/declared_fold.hpp index 4d7aa9039..624074cfd 100644 --- a/phlex/core/declared_fold.hpp +++ b/phlex/core/declared_fold.hpp @@ -56,10 +56,10 @@ namespace phlex::experimental { class fold_node : public declared_fold, private count_stores { using all_parameter_types = typename AlgorithmBits::input_parameter_types; using input_parameter_types = skip_first_type; // Skip fold object - static constexpr auto N = std::tuple_size_v; - using R = std::decay_t>; + static constexpr auto num_inputs = std::tuple_size_v; + using r = std::decay_t>; - static constexpr std::size_t M = 1; // hard-coded for now + static constexpr std::size_t num_outputs = 1; // hard-coded for now using function_t = typename AlgorithmBits::bound_type; public: @@ -74,7 +74,7 @@ namespace phlex::experimental { std::string partition) : declared_fold{std::move(name), std::move(predicates), std::move(product_labels)}, initializer_{std::move(initializer)}, - output_{to_product_specifications(full_name(), std::move(output), make_type_ids())}, + output_{to_product_specifications(full_name(), std::move(output), make_type_ids())}, partition_{std::move(partition)}, flush_receiver_{g, tbb::flow::unlimited, @@ -88,32 +88,33 @@ namespace phlex::experimental { emit_and_evict_if_done(index); return {}; }}, - join_{make_join_or_none( + join_{make_join_or_none( g, full_name(), layers())}, // FIXME: This should change to include result product! - fold_{ - g, concurrency, [this, ft = alg.release_algorithm()](messages_t const& messages, auto&) { - // N.B. The assumption is that a fold will *never* need to cache - // the product store it creates. Any flush messages *do not* need - // to be propagated to downstream nodes. - auto const& msg = most_derived(messages); - auto const& index = msg.store->index(); + fold_{g, + concurrency, + [this, ft = alg.release_algorithm()](messages_t const& messages, auto&) { + // N.B. The assumption is that a fold will *never* need to cache + // the product store it creates. Any flush messages *do not* need + // to be propagated to downstream nodes. + auto const& msg = most_derived(messages); + auto const& index = msg.store->index(); - auto fold_index = index->parent(partition_); - if (not fold_index) { - return; - } + auto fold_index = index->parent(partition_); + if (not fold_index) { + return; + } - auto const& index_hash_for_counter = fold_index->hash(); + auto const& index_hash_for_counter = fold_index->hash(); - call(ft, messages, std::make_index_sequence{}); - ++calls_; + call(ft, messages, std::make_index_sequence{}); + ++calls_; - counter_for(index_hash_for_counter).increment(index->layer_hash()); + counter_for(index_hash_for_counter).increment(index->layer_hash()); - emit_and_evict_if_done(fold_index); - }} + emit_and_evict_if_done(fold_index); + }} { - if constexpr (N > 1ull) { + if constexpr (num_inputs > 1ull) { make_edge(join_, fold_); } } @@ -123,7 +124,7 @@ namespace phlex::experimental { { if (auto counter = done_with(fold_index->hash())) { auto parent = std::make_shared(fold_index, this->full_name()); - commit_(parent); + commit(parent); ++product_count_; tbb::flow::output_port<0>(fold_).try_put( {.store = parent, .id = counter->original_message_id()}); @@ -132,12 +133,12 @@ namespace phlex::experimental { tbb::flow::receiver& port_for(product_query const& product_label) override { - return receiver_for(join_, input(), product_label, fold_); + return receiver_for(join_, input(), product_label, fold_); } std::vector*> ports() override { - return input_ports(join_, fold_); + return input_ports(join_, fold_); } tbb::flow::receiver& flush_port() override { return flush_receiver_; } @@ -145,7 +146,9 @@ namespace phlex::experimental { product_specifications const& output() const override { return output_; } template - void call(function_t const& ft, messages_t const& messages, std::index_sequence) + void call(function_t const& ft, + messages_t const& messages, + std::index_sequence) { auto const parent_index = most_derived(messages).store->index()->parent(partition_); @@ -160,7 +163,7 @@ namespace phlex::experimental { .first; } - if constexpr (N == 1ull) { + if constexpr (num_inputs == 1ull) { std::invoke(ft, *it->second, std::get(input_).retrieve(messages)...); } else { std::invoke(ft, *it->second, std::get(input_).retrieve(std::get(messages))...); @@ -174,11 +177,11 @@ namespace phlex::experimental { template auto initialized_object(InitTuple&& tuple, std::index_sequence) const { - return std::unique_ptr{ - new R{std::forward>(std::get(tuple))...}}; + return std::unique_ptr{ + new r{std::forward>(std::get(tuple))...}}; } - auto commit_(product_store_ptr& store) + auto commit(product_store_ptr& store) { auto& result = results_.at(store->index()->hash()); if constexpr (requires { send(*result); }) { @@ -196,9 +199,9 @@ namespace phlex::experimental { product_specifications output_; std::string partition_; tbb::flow::function_node flush_receiver_; - join_or_none_t join_; - tbb::flow::multifunction_node, message_tuple<1>> fold_; - tbb::concurrent_unordered_map> results_; + join_or_none_t join_; + tbb::flow::multifunction_node, message_tuple<1>> fold_; + tbb::concurrent_unordered_map> results_; std::atomic calls_; std::atomic product_count_; }; diff --git a/phlex/core/declared_observer.hpp b/phlex/core/declared_observer.hpp index f9d8287a4..d1bea85e8 100644 --- a/phlex/core/declared_observer.hpp +++ b/phlex/core/declared_observer.hpp @@ -45,9 +45,9 @@ namespace phlex::experimental { template class observer_node : public declared_observer { - using InputArgs = typename AlgorithmBits::input_parameter_types; + using input_args = typename AlgorithmBits::input_parameter_types; using function_t = typename AlgorithmBits::bound_type; - static constexpr auto N = AlgorithmBits::number_inputs; + static constexpr auto num_inputs = AlgorithmBits::number_inputs; public: static constexpr auto number_output_products = 0; @@ -60,17 +60,17 @@ namespace phlex::experimental { AlgorithmBits alg, product_queries input_products) : declared_observer{std::move(name), std::move(predicates), std::move(input_products)}, - join_{make_join_or_none(g, full_name(), layers())}, + join_{make_join_or_none(g, full_name(), layers())}, observer_{g, concurrency, [this, ft = alg.release_algorithm()]( - messages_t const& messages) -> oneapi::tbb::flow::continue_msg { - call(ft, messages, std::make_index_sequence{}); + messages_t const& messages) -> oneapi::tbb::flow::continue_msg { + call(ft, messages, std::make_index_sequence{}); ++calls_; return {}; }} { - if constexpr (N > 1ull) { + if constexpr (num_inputs > 1ull) { make_edge(join_, observer_); } } @@ -78,18 +78,20 @@ namespace phlex::experimental { private: tbb::flow::receiver& port_for(product_query const& product_label) override { - return receiver_for(join_, input(), product_label, observer_); + return receiver_for(join_, input(), product_label, observer_); } std::vector*> ports() override { - return input_ports(join_, observer_); + return input_ports(join_, observer_); } template - void call(function_t const& ft, messages_t const& messages, std::index_sequence) + void call(function_t const& ft, + messages_t const& messages, + std::index_sequence) { - if constexpr (N == 1ull) { + if constexpr (num_inputs == 1ull) { std::invoke(ft, std::get(input_).retrieve(messages)...); } else { std::invoke(ft, std::get(input_).retrieve(std::get(messages))...); @@ -99,9 +101,9 @@ namespace phlex::experimental { named_index_ports index_ports() final { return join_.index_ports(); } std::size_t num_calls() const final { return calls_.load(); } - input_retriever_types input_{input_arguments()}; - join_or_none_t join_; - tbb::flow::function_node> observer_; + input_retriever_types input_{input_arguments()}; + join_or_none_t join_; + tbb::flow::function_node> observer_; std::atomic calls_; }; } diff --git a/phlex/core/declared_predicate.hpp b/phlex/core/declared_predicate.hpp index dfc847839..72643c7da 100644 --- a/phlex/core/declared_predicate.hpp +++ b/phlex/core/declared_predicate.hpp @@ -49,9 +49,9 @@ namespace phlex::experimental { template class predicate_node : public declared_predicate { - using InputArgs = typename AlgorithmBits::input_parameter_types; + using input_args = typename AlgorithmBits::input_parameter_types; using function_t = typename AlgorithmBits::bound_type; - static constexpr auto N = AlgorithmBits::number_inputs; + static constexpr auto num_inputs = AlgorithmBits::number_inputs; public: static constexpr auto number_output_products = 0ull; @@ -64,20 +64,20 @@ namespace phlex::experimental { AlgorithmBits alg, product_queries input_products) : declared_predicate{std::move(name), std::move(predicates), std::move(input_products)}, - join_{make_join_or_none(g, full_name(), layers())}, - predicate_{ - g, - concurrency, - [this, ft = alg.release_algorithm()](messages_t const& messages) -> predicate_result { - auto const& msg = most_derived(messages); - auto const& [store, message_id] = std::tie(msg.store, msg.id); - - bool const rc = call(ft, messages, std::make_index_sequence{}); - ++calls_; - return {message_id, rc}; - }} + join_{make_join_or_none(g, full_name(), layers())}, + predicate_{g, + concurrency, + [this, ft = alg.release_algorithm()]( + messages_t const& messages) -> predicate_result { + auto const& msg = most_derived(messages); + auto const& [store, message_id] = std::tie(msg.store, msg.id); + + bool const rc = call(ft, messages, std::make_index_sequence{}); + ++calls_; + return {message_id, rc}; + }} { - if constexpr (N > 1ull) { + if constexpr (num_inputs > 1ull) { make_edge(join_, predicate_); } } @@ -85,19 +85,21 @@ namespace phlex::experimental { private: tbb::flow::receiver& port_for(product_query const& product_label) override { - return receiver_for(join_, input(), product_label, predicate_); + return receiver_for(join_, input(), product_label, predicate_); } std::vector*> ports() override { - return input_ports(join_, predicate_); + return input_ports(join_, predicate_); } tbb::flow::sender& sender() override { return predicate_; } template - bool call(function_t const& ft, messages_t const& messages, std::index_sequence) + bool call(function_t const& ft, + messages_t const& messages, + std::index_sequence) { - if constexpr (N == 1ull) { + if constexpr (num_inputs == 1ull) { return std::invoke(ft, std::get(input_).retrieve(messages)...); } else { return std::invoke(ft, std::get(input_).retrieve(std::get(messages))...); @@ -107,9 +109,9 @@ namespace phlex::experimental { named_index_ports index_ports() final { return join_.index_ports(); } std::size_t num_calls() const final { return calls_.load(); } - input_retriever_types input_{input_arguments()}; - join_or_none_t join_; - tbb::flow::function_node, predicate_result> predicate_; + input_retriever_types input_{input_arguments()}; + join_or_none_t join_; + tbb::flow::function_node, predicate_result> predicate_; std::atomic calls_; }; diff --git a/phlex/core/declared_transform.hpp b/phlex/core/declared_transform.hpp index 8ce6c656c..34358cd8d 100644 --- a/phlex/core/declared_transform.hpp +++ b/phlex/core/declared_transform.hpp @@ -58,12 +58,12 @@ namespace phlex::experimental { using function_t = typename AlgorithmBits::bound_type; using input_parameter_types = typename AlgorithmBits::input_parameter_types; - static constexpr auto N = AlgorithmBits::number_inputs; - static constexpr auto M = number_output_objects; + static constexpr auto num_inputs = AlgorithmBits::number_inputs; + static constexpr auto num_outputs = number_output_objects; public: using node_ptr_type = declared_transform_ptr; - static constexpr auto number_output_products = M; + static constexpr auto number_output_products = num_outputs; transform_node(algorithm_name name, std::size_t concurrency, @@ -75,26 +75,27 @@ namespace phlex::experimental { declared_transform{std::move(name), std::move(predicates), std::move(input_products)}, output_{to_product_specifications( full_name(), std::move(output), make_output_type_ids())}, - join_{make_join_or_none(g, full_name(), layers())}, - transform_{g, - concurrency, - [this, ft = alg.release_algorithm()](messages_t const& messages, auto& output) { - auto const& msg = most_derived(messages); - auto const& [store, message_id] = std::tie(msg.store, msg.id); - - auto result = call(ft, messages, std::make_index_sequence{}); - ++calls_; - ++product_count_[store->index()->layer_hash()]; - - products new_products; - new_products.add_all(output_, std::move(result)); - auto new_store = std::make_shared( - store->index(), this->full_name(), std::move(new_products)); - - std::get<0>(output).try_put({.store = std::move(new_store), .id = message_id}); - }} + join_{make_join_or_none(g, full_name(), layers())}, + transform_{ + g, + concurrency, + [this, ft = alg.release_algorithm()](messages_t const& messages, auto& output) { + auto const& msg = most_derived(messages); + auto const& [store, message_id] = std::tie(msg.store, msg.id); + + auto result = call(ft, messages, std::make_index_sequence{}); + ++calls_; + ++product_count_[store->index()->layer_hash()]; + + products new_products; + new_products.add_all(output_, std::move(result)); + auto new_store = std::make_shared( + store->index(), this->full_name(), std::move(new_products)); + + std::get<0>(output).try_put({.store = std::move(new_store), .id = message_id}); + }} { - if constexpr (N > 1ull) { + if constexpr (num_inputs > 1ull) { make_edge(join_, transform_); } } @@ -102,12 +103,12 @@ namespace phlex::experimental { private: tbb::flow::receiver& port_for(product_query const& product_label) override { - return receiver_for(join_, input(), product_label, transform_); + return receiver_for(join_, input(), product_label, transform_); } std::vector*> ports() override { - return input_ports(join_, transform_); + return input_ports(join_, transform_); } tbb::flow::sender& output_port() override @@ -117,9 +118,11 @@ namespace phlex::experimental { product_specifications const& output() const override { return output_; } template - auto call(function_t const& ft, messages_t const& messages, std::index_sequence) + auto call(function_t const& ft, + messages_t const& messages, + std::index_sequence) { - if constexpr (N == 1ull) { + if constexpr (num_inputs == 1ull) { return std::invoke(ft, std::get(input_).retrieve(messages)...); } else { return std::invoke(ft, std::get(input_).retrieve(std::get(messages))...); @@ -139,8 +142,8 @@ namespace phlex::experimental { input_retriever_types input_{input_arguments()}; product_specifications output_; - join_or_none_t join_; - tbb::flow::multifunction_node, message_tuple<1u>> transform_; + join_or_none_t join_; + tbb::flow::multifunction_node, message_tuple<1u>> transform_; std::atomic calls_; tbb::concurrent_unordered_map> product_count_; }; diff --git a/phlex/core/declared_unfold.hpp b/phlex/core/declared_unfold.hpp index d64621f1d..6349637c7 100644 --- a/phlex/core/declared_unfold.hpp +++ b/phlex/core/declared_unfold.hpp @@ -79,9 +79,9 @@ namespace phlex::experimental { template class unfold_node : public declared_unfold { - using InputArgs = constructor_parameter_types; - static constexpr std::size_t N = std::tuple_size_v; - static constexpr std::size_t M = number_output_objects; + using input_args = constructor_parameter_types; + static constexpr std::size_t num_inputs = std::tuple_size_v; + static constexpr std::size_t num_outputs = number_output_objects; public: unfold_node(algorithm_name name, @@ -100,17 +100,17 @@ namespace phlex::experimental { output_{to_product_specifications(full_name(), std::move(output_products), make_type_ids>>())}, - join_{make_join_or_none(g, full_name(), layers())}, + join_{make_join_or_none(g, full_name(), layers())}, unfold_{g, concurrency, [this, p = std::move(predicate), ufold = std::move(unfold)]( - messages_t const& messages, auto&) { + messages_t const& messages, auto&) { auto const& msg = most_derived(messages); auto const& store = msg.store; std::size_t const original_message_id{msg_counter_}; generator g{store, this->full_name(), child_layer()}; - call(p, ufold, store->index(), g, messages, std::make_index_sequence{}); + call(p, ufold, store->index(), g, messages, std::make_index_sequence{}); flusher_.try_put({.index = store->index(), .counts = g.flush_result(), @@ -118,7 +118,7 @@ namespace phlex::experimental { }}, flusher_{g} { - if constexpr (N > 1ull) { + if constexpr (num_inputs > 1ull) { make_edge(join_, unfold_); } } @@ -126,11 +126,11 @@ namespace phlex::experimental { private: tbb::flow::receiver& port_for(product_query const& product_label) override { - return receiver_for(join_, input(), product_label, unfold_); + return receiver_for(join_, input(), product_label, unfold_); } std::vector*> ports() override { - return input_ports(join_, unfold_); + return input_ports(join_, unfold_); } tbb::flow::sender& output_port() override @@ -149,12 +149,12 @@ namespace phlex::experimental { Unfold const& unfold, data_cell_index_ptr const& unfolded_id, generator& g, - messages_t const& messages, + messages_t const& messages, std::index_sequence) { ++calls_; Object obj = [this, &messages]() { - if constexpr (N == 1ull) { + if constexpr (num_inputs == 1ull) { return Object(std::get(input_).retrieve(messages)...); } else { return Object(std::get(input_).retrieve(std::get(messages))...); @@ -187,10 +187,11 @@ namespace phlex::experimental { std::size_t num_calls() const final { return calls_.load(); } std::size_t product_count() const final { return product_count_.load(); } - input_retriever_types input_{input_arguments()}; + input_retriever_types input_{input_arguments()}; product_specifications output_; - join_or_none_t join_; - tbb::flow::multifunction_node, std::tuple> unfold_; + join_or_none_t join_; + tbb::flow::multifunction_node, std::tuple> + unfold_; flusher_t flusher_; std::atomic msg_counter_{}; // Is this sufficient? Probably not. std::atomic calls_{}; diff --git a/phlex/core/input_arguments.hpp b/phlex/core/input_arguments.hpp index 4e7e429e1..1ad1b5c29 100644 --- a/phlex/core/input_arguments.hpp +++ b/phlex/core/input_arguments.hpp @@ -36,9 +36,9 @@ namespace phlex::experimental { template auto form_input_arguments(std::string const& algorithm_name, product_queries const& args) { - constexpr auto N = std::tuple_size_v; + constexpr auto num_inputs = std::tuple_size_v; detail::verify_no_duplicate_input_products(algorithm_name, args); - return form_input_arguments_impl(args, std::make_index_sequence{}); + return form_input_arguments_impl(args, std::make_index_sequence{}); } template diff --git a/phlex/core/multilayer_join_node.hpp b/phlex/core/multilayer_join_node.hpp index 0d281d7c2..b1743de44 100644 --- a/phlex/core/multilayer_join_node.hpp +++ b/phlex/core/multilayer_join_node.hpp @@ -43,14 +43,14 @@ namespace phlex::experimental { // ├──► join_node ──► message tuple // data[N-1] ──┘ - template - requires(n_inputs > 1) - class multilayer_join_node : public multilayer_join_node_base_t> { - using base_t = multilayer_join_node_base_t>; + template + requires(NInputs > 1) + class multilayer_join_node : public multilayer_join_node_base_t> { + using base_t = multilayer_join_node_base_t>; using input_t = typename base_t::input_ports_type; using output_t = typename base_t::output_ports_type; - using args_t = message_tuple; + using args_t = message_tuple; template static auto make_join(tbb::flow::graph& g, std::index_sequence) @@ -68,11 +68,11 @@ namespace phlex::experimental { std::string const& node_name, std::vector layer_names) : base_t{g}, - join_{make_join(g, std::make_index_sequence{})}, + join_{make_join(g, std::make_index_sequence{})}, name_{node_name}, layers_{std::move(layer_names)} { - assert(n_inputs == layers_.size()); + assert(NInputs == layers_.size()); // Collapse to the set of distinct layer names. More than one distinct layer means // at least one input crosses a layer boundary and therefore every input stream @@ -81,7 +81,7 @@ namespace phlex::experimental { // Add repeaters only if the inputs span more than one distinct layer. if (collapsed_layers.size() > 1) { - repeaters_.reserve(n_inputs); + repeaters_.reserve(NInputs); for (auto const& layer : layers_) { repeaters_.push_back(std::make_unique(g, name_, layer)); } @@ -99,7 +99,7 @@ namespace phlex::experimental { } }; - set_ports(std::make_index_sequence{}); + set_ports(std::make_index_sequence{}); } // Returns one named_index_port per repeater so that the index router can deliver diff --git a/phlex/core/registrar.hpp b/phlex/core/registrar.hpp index 92ef9e55b..45c6dab2b 100644 --- a/phlex/core/registrar.hpp +++ b/phlex/core/registrar.hpp @@ -63,11 +63,11 @@ namespace phlex::experimental { template class registrar { - using Nodes = simple_ptr_map; + using nodes = simple_ptr_map; using node_creator = std::function, std::vector)>; public: - explicit registrar(Nodes& nodes, std::vector& errors) : + explicit registrar(nodes& nodes, std::vector& errors) : nodes_{&nodes}, errors_{&errors} { } @@ -116,7 +116,7 @@ namespace phlex::experimental { } } - Nodes* nodes_; + nodes* nodes_; std::vector* errors_; node_creator creator_{}; std::optional> predicates_; diff --git a/phlex/core/registration_api.hpp b/phlex/core/registration_api.hpp index e11bb6b36..ce4d8e5b4 100644 --- a/phlex/core/registration_api.hpp +++ b/phlex/core/registration_api.hpp @@ -27,11 +27,11 @@ namespace phlex::experimental { template