diff --git a/include/oneapi/tbb/detail/_flow_graph_indexer_impl.h b/include/oneapi/tbb/detail/_flow_graph_indexer_impl.h index a743310079..7c9a04ec6a 100644 --- a/include/oneapi/tbb/detail/_flow_graph_indexer_impl.h +++ b/include/oneapi/tbb/detail/_flow_graph_indexer_impl.h @@ -1,5 +1,6 @@ /* - Copyright (c) 2005-2024 Intel Corporation + Copyright (c) 2005-2025 Intel Corporation + Copyright (c) 2025 UXL Foundation Contributors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -222,146 +223,23 @@ broadcast_cache my_successors; }; //indexer_node_base - - template struct input_types; - - template - struct input_types<1, InputTuple> { - typedef typename std::tuple_element<0, InputTuple>::type first_type; - typedef tagged_msg type; - }; - - template - struct input_types<2, InputTuple> { - typedef typename std::tuple_element<0, InputTuple>::type first_type; - typedef typename std::tuple_element<1, InputTuple>::type second_type; - typedef tagged_msg type; - }; - - template - struct input_types<3, InputTuple> { - typedef typename std::tuple_element<0, InputTuple>::type first_type; - typedef typename std::tuple_element<1, InputTuple>::type second_type; - typedef typename std::tuple_element<2, InputTuple>::type third_type; - typedef tagged_msg type; - }; - - template - struct input_types<4, InputTuple> { - typedef typename std::tuple_element<0, InputTuple>::type first_type; - typedef typename std::tuple_element<1, InputTuple>::type second_type; - typedef typename std::tuple_element<2, InputTuple>::type third_type; - typedef typename std::tuple_element<3, InputTuple>::type fourth_type; - typedef tagged_msg type; - }; - - template - struct input_types<5, InputTuple> { - typedef typename std::tuple_element<0, InputTuple>::type first_type; - typedef typename std::tuple_element<1, InputTuple>::type second_type; - typedef typename std::tuple_element<2, InputTuple>::type third_type; - typedef typename std::tuple_element<3, InputTuple>::type fourth_type; - typedef typename std::tuple_element<4, InputTuple>::type fifth_type; - typedef tagged_msg type; - }; - - template - struct input_types<6, InputTuple> { - typedef typename std::tuple_element<0, InputTuple>::type first_type; - typedef typename std::tuple_element<1, InputTuple>::type second_type; - typedef typename std::tuple_element<2, InputTuple>::type third_type; - typedef typename std::tuple_element<3, InputTuple>::type fourth_type; - typedef typename std::tuple_element<4, InputTuple>::type fifth_type; - typedef typename std::tuple_element<5, InputTuple>::type sixth_type; - typedef tagged_msg type; - }; - - template - struct input_types<7, InputTuple> { - typedef typename std::tuple_element<0, InputTuple>::type first_type; - typedef typename std::tuple_element<1, InputTuple>::type second_type; - typedef typename std::tuple_element<2, InputTuple>::type third_type; - typedef typename std::tuple_element<3, InputTuple>::type fourth_type; - typedef typename std::tuple_element<4, InputTuple>::type fifth_type; - typedef typename std::tuple_element<5, InputTuple>::type sixth_type; - typedef typename std::tuple_element<6, InputTuple>::type seventh_type; - typedef tagged_msg type; - }; - - - template - struct input_types<8, InputTuple> { - typedef typename std::tuple_element<0, InputTuple>::type first_type; - typedef typename std::tuple_element<1, InputTuple>::type second_type; - typedef typename std::tuple_element<2, InputTuple>::type third_type; - typedef typename std::tuple_element<3, InputTuple>::type fourth_type; - typedef typename std::tuple_element<4, InputTuple>::type fifth_type; - typedef typename std::tuple_element<5, InputTuple>::type sixth_type; - typedef typename std::tuple_element<6, InputTuple>::type seventh_type; - typedef typename std::tuple_element<7, InputTuple>::type eighth_type; - typedef tagged_msg type; - }; - - - template - struct input_types<9, InputTuple> { - typedef typename std::tuple_element<0, InputTuple>::type first_type; - typedef typename std::tuple_element<1, InputTuple>::type second_type; - typedef typename std::tuple_element<2, InputTuple>::type third_type; - typedef typename std::tuple_element<3, InputTuple>::type fourth_type; - typedef typename std::tuple_element<4, InputTuple>::type fifth_type; - typedef typename std::tuple_element<5, InputTuple>::type sixth_type; - typedef typename std::tuple_element<6, InputTuple>::type seventh_type; - typedef typename std::tuple_element<7, InputTuple>::type eighth_type; - typedef typename std::tuple_element<8, InputTuple>::type nineth_type; - typedef tagged_msg type; - }; - - template - struct input_types<10, InputTuple> { - typedef typename std::tuple_element<0, InputTuple>::type first_type; - typedef typename std::tuple_element<1, InputTuple>::type second_type; - typedef typename std::tuple_element<2, InputTuple>::type third_type; - typedef typename std::tuple_element<3, InputTuple>::type fourth_type; - typedef typename std::tuple_element<4, InputTuple>::type fifth_type; - typedef typename std::tuple_element<5, InputTuple>::type sixth_type; - typedef typename std::tuple_element<6, InputTuple>::type seventh_type; - typedef typename std::tuple_element<7, InputTuple>::type eighth_type; - typedef typename std::tuple_element<8, InputTuple>::type nineth_type; - typedef typename std::tuple_element<9, InputTuple>::type tenth_type; - typedef tagged_msg type; - }; - // type generators - template - struct indexer_types : public input_types::value, OutputTuple> { - static const int N = std::tuple_size::value; - typedef typename input_types::type output_type; - typedef typename wrap_tuple_elements::type input_ports_type; - typedef indexer_node_FE indexer_FE_type; - typedef indexer_node_base indexer_base_type; + template + struct indexer_types { + using output_type = tagged_msg; + using input_ports_type = std::tuple...>; + using indexer_base_type = indexer_node_base>; }; - template - class unfolded_indexer_node : public indexer_types::indexer_base_type { + template + class unfolded_indexer_node : public indexer_types::indexer_base_type { public: - typedef typename indexer_types::input_ports_type input_ports_type; - typedef OutputTuple tuple_types; - typedef typename indexer_types::output_type output_type; + using input_ports_type = typename indexer_types::input_ports_type; + using output_type = typename indexer_types::output_type; + using tuple_types = std::tuple; + private: - typedef typename indexer_types::indexer_base_type base_type; + using base_type = typename indexer_types::indexer_base_type; public: unfolded_indexer_node(graph& g) : base_type(g) {} unfolded_indexer_node(const unfolded_indexer_node &other) : base_type(other) {} diff --git a/include/oneapi/tbb/detail/_flow_graph_join_impl.h b/include/oneapi/tbb/detail/_flow_graph_join_impl.h index 8bca9a2c41..706df447a9 100644 --- a/include/oneapi/tbb/detail/_flow_graph_join_impl.h +++ b/include/oneapi/tbb/detail/_flow_graph_join_impl.h @@ -1,5 +1,6 @@ /* - Copyright (c) 2005-2024 Intel Corporation + Copyright (c) 2005-2025 Intel Corporation + Copyright (c) 2025 UXL Foundation Contributors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -1456,36 +1457,23 @@ }; // join_node_base // join base class type generator - template class PT, typename OutputTuple, typename JP> + template class PortType, typename OutputTuple, typename JoinPolicy> struct join_base { - typedef join_node_base::type, OutputTuple> type; + using type = join_node_base::type, + OutputTuple>; }; - template - struct join_base > { - typedef key_matching key_traits_type; - typedef K key_type; - typedef KHash key_hash_compare; - typedef join_node_base< key_traits_type, - // ports type - typename wrap_key_tuple_elements::type, - OutputTuple > type; - }; - - //! unfolded_join_node : passes input_ports_type to join_node_base. We build the input port type - // using tuple_element. The class PT is the port type (reserving_port, queueing_port, key_matching_port) - // and should match the typename. + template + struct join_base > { + using key_type = K; + using key_hash_compare = KHash; + using key_traits_type = key_matching; - template class PT, typename OutputTuple, typename JP> - class unfolded_join_node : public join_base::type { - public: - typedef typename wrap_tuple_elements::type input_ports_type; - typedef OutputTuple output_type; - private: - typedef join_node_base base_type; - public: - unfolded_join_node(graph &g) : base_type(g) {} - unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} + using type = join_node_base::type, + OutputTuple>; }; #if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING @@ -1503,463 +1491,49 @@ } }; #endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */ - // key_matching unfolded_join_node. This must be a separate specialization because the constructors - // differ. - - template - class unfolded_join_node<2,key_matching_port,OutputTuple,key_matching > : public - join_base<2,key_matching_port,OutputTuple,key_matching >::type { - typedef typename std::tuple_element<0, OutputTuple>::type T0; - typedef typename std::tuple_element<1, OutputTuple>::type T1; - public: - typedef typename wrap_key_tuple_elements<2,key_matching_port,key_matching,OutputTuple>::type input_ports_type; - typedef OutputTuple output_type; - private: - typedef join_node_base, input_ports_type, output_type > base_type; - typedef type_to_key_function_body *f0_p; - typedef type_to_key_function_body *f1_p; - typedef std::tuple< f0_p, f1_p > func_initializer_type; - public: -#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING - unfolded_join_node(graph &g) : base_type(g, - func_initializer_type( - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()) - ) ) { - } -#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */ - template - unfolded_join_node(graph &g, Body0 body0, Body1 body1) : base_type(g, - func_initializer_type( - new type_to_key_function_body_leaf(body0), - new type_to_key_function_body_leaf(body1) - ) ) { - static_assert(std::tuple_size::value == 2, "wrong number of body initializers"); - } - unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} - }; - - template - class unfolded_join_node<3,key_matching_port,OutputTuple,key_matching > : public - join_base<3,key_matching_port,OutputTuple,key_matching >::type { - typedef typename std::tuple_element<0, OutputTuple>::type T0; - typedef typename std::tuple_element<1, OutputTuple>::type T1; - typedef typename std::tuple_element<2, OutputTuple>::type T2; - public: - typedef typename wrap_key_tuple_elements<3,key_matching_port,key_matching,OutputTuple>::type input_ports_type; - typedef OutputTuple output_type; - private: - typedef join_node_base, input_ports_type, output_type > base_type; - typedef type_to_key_function_body *f0_p; - typedef type_to_key_function_body *f1_p; - typedef type_to_key_function_body *f2_p; - typedef std::tuple< f0_p, f1_p, f2_p > func_initializer_type; - public: -#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING - unfolded_join_node(graph &g) : base_type(g, - func_initializer_type( - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()) - ) ) { - } -#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */ - template - unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2) : base_type(g, - func_initializer_type( - new type_to_key_function_body_leaf(body0), - new type_to_key_function_body_leaf(body1), - new type_to_key_function_body_leaf(body2) - ) ) { - static_assert(std::tuple_size::value == 3, "wrong number of body initializers"); - } - unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} - }; - - template - class unfolded_join_node<4,key_matching_port,OutputTuple,key_matching > : public - join_base<4,key_matching_port,OutputTuple,key_matching >::type { - typedef typename std::tuple_element<0, OutputTuple>::type T0; - typedef typename std::tuple_element<1, OutputTuple>::type T1; - typedef typename std::tuple_element<2, OutputTuple>::type T2; - typedef typename std::tuple_element<3, OutputTuple>::type T3; - public: - typedef typename wrap_key_tuple_elements<4,key_matching_port,key_matching,OutputTuple>::type input_ports_type; - typedef OutputTuple output_type; - private: - typedef join_node_base, input_ports_type, output_type > base_type; - typedef type_to_key_function_body *f0_p; - typedef type_to_key_function_body *f1_p; - typedef type_to_key_function_body *f2_p; - typedef type_to_key_function_body *f3_p; - typedef std::tuple< f0_p, f1_p, f2_p, f3_p > func_initializer_type; - public: -#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING - unfolded_join_node(graph &g) : base_type(g, - func_initializer_type( - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()) - ) ) { - } -#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */ - template - unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3) : base_type(g, - func_initializer_type( - new type_to_key_function_body_leaf(body0), - new type_to_key_function_body_leaf(body1), - new type_to_key_function_body_leaf(body2), - new type_to_key_function_body_leaf(body3) - ) ) { - static_assert(std::tuple_size::value == 4, "wrong number of body initializers"); - } - unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} - }; - - template - class unfolded_join_node<5,key_matching_port,OutputTuple,key_matching > : public - join_base<5,key_matching_port,OutputTuple,key_matching >::type { - typedef typename std::tuple_element<0, OutputTuple>::type T0; - typedef typename std::tuple_element<1, OutputTuple>::type T1; - typedef typename std::tuple_element<2, OutputTuple>::type T2; - typedef typename std::tuple_element<3, OutputTuple>::type T3; - typedef typename std::tuple_element<4, OutputTuple>::type T4; - public: - typedef typename wrap_key_tuple_elements<5,key_matching_port,key_matching,OutputTuple>::type input_ports_type; - typedef OutputTuple output_type; - private: - typedef join_node_base , input_ports_type, output_type > base_type; - typedef type_to_key_function_body *f0_p; - typedef type_to_key_function_body *f1_p; - typedef type_to_key_function_body *f2_p; - typedef type_to_key_function_body *f3_p; - typedef type_to_key_function_body *f4_p; - typedef std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p > func_initializer_type; - public: -#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING - unfolded_join_node(graph &g) : base_type(g, - func_initializer_type( - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()) - ) ) { - } -#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */ - template - unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4) : base_type(g, - func_initializer_type( - new type_to_key_function_body_leaf(body0), - new type_to_key_function_body_leaf(body1), - new type_to_key_function_body_leaf(body2), - new type_to_key_function_body_leaf(body3), - new type_to_key_function_body_leaf(body4) - ) ) { - static_assert(std::tuple_size::value == 5, "wrong number of body initializers"); - } - unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} - }; - -#if __TBB_VARIADIC_MAX >= 6 - template - class unfolded_join_node<6,key_matching_port,OutputTuple,key_matching > : public - join_base<6,key_matching_port,OutputTuple,key_matching >::type { - typedef typename std::tuple_element<0, OutputTuple>::type T0; - typedef typename std::tuple_element<1, OutputTuple>::type T1; - typedef typename std::tuple_element<2, OutputTuple>::type T2; - typedef typename std::tuple_element<3, OutputTuple>::type T3; - typedef typename std::tuple_element<4, OutputTuple>::type T4; - typedef typename std::tuple_element<5, OutputTuple>::type T5; - public: - typedef typename wrap_key_tuple_elements<6,key_matching_port,key_matching,OutputTuple>::type input_ports_type; - typedef OutputTuple output_type; - private: - typedef join_node_base , input_ports_type, output_type > base_type; - typedef type_to_key_function_body *f0_p; - typedef type_to_key_function_body *f1_p; - typedef type_to_key_function_body *f2_p; - typedef type_to_key_function_body *f3_p; - typedef type_to_key_function_body *f4_p; - typedef type_to_key_function_body *f5_p; - typedef std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p > func_initializer_type; - public: -#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING - unfolded_join_node(graph &g) : base_type(g, - func_initializer_type( - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()) - ) ) { - } -#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */ - template - unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4, Body5 body5) - : base_type(g, func_initializer_type( - new type_to_key_function_body_leaf(body0), - new type_to_key_function_body_leaf(body1), - new type_to_key_function_body_leaf(body2), - new type_to_key_function_body_leaf(body3), - new type_to_key_function_body_leaf(body4), - new type_to_key_function_body_leaf(body5) - ) ) { - static_assert(std::tuple_size::value == 6, "wrong number of body initializers"); - } - unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} - }; -#endif - -#if __TBB_VARIADIC_MAX >= 7 - template - class unfolded_join_node<7,key_matching_port,OutputTuple,key_matching > : public - join_base<7,key_matching_port,OutputTuple,key_matching >::type { - typedef typename std::tuple_element<0, OutputTuple>::type T0; - typedef typename std::tuple_element<1, OutputTuple>::type T1; - typedef typename std::tuple_element<2, OutputTuple>::type T2; - typedef typename std::tuple_element<3, OutputTuple>::type T3; - typedef typename std::tuple_element<4, OutputTuple>::type T4; - typedef typename std::tuple_element<5, OutputTuple>::type T5; - typedef typename std::tuple_element<6, OutputTuple>::type T6; - public: - typedef typename wrap_key_tuple_elements<7,key_matching_port,key_matching,OutputTuple>::type input_ports_type; - typedef OutputTuple output_type; - private: - typedef join_node_base , input_ports_type, output_type > base_type; - typedef type_to_key_function_body *f0_p; - typedef type_to_key_function_body *f1_p; - typedef type_to_key_function_body *f2_p; - typedef type_to_key_function_body *f3_p; - typedef type_to_key_function_body *f4_p; - typedef type_to_key_function_body *f5_p; - typedef type_to_key_function_body *f6_p; - typedef std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p > func_initializer_type; - public: -#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING - unfolded_join_node(graph &g) : base_type(g, - func_initializer_type( - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()) - ) ) { - } -#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */ - template - unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4, - Body5 body5, Body6 body6) : base_type(g, func_initializer_type( - new type_to_key_function_body_leaf(body0), - new type_to_key_function_body_leaf(body1), - new type_to_key_function_body_leaf(body2), - new type_to_key_function_body_leaf(body3), - new type_to_key_function_body_leaf(body4), - new type_to_key_function_body_leaf(body5), - new type_to_key_function_body_leaf(body6) - ) ) { - static_assert(std::tuple_size::value == 7, "wrong number of body initializers"); - } - unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} - }; -#endif -#if __TBB_VARIADIC_MAX >= 8 - template - class unfolded_join_node<8,key_matching_port,OutputTuple,key_matching > : public - join_base<8,key_matching_port,OutputTuple,key_matching >::type { - typedef typename std::tuple_element<0, OutputTuple>::type T0; - typedef typename std::tuple_element<1, OutputTuple>::type T1; - typedef typename std::tuple_element<2, OutputTuple>::type T2; - typedef typename std::tuple_element<3, OutputTuple>::type T3; - typedef typename std::tuple_element<4, OutputTuple>::type T4; - typedef typename std::tuple_element<5, OutputTuple>::type T5; - typedef typename std::tuple_element<6, OutputTuple>::type T6; - typedef typename std::tuple_element<7, OutputTuple>::type T7; + //! unfolded_join_node : passes input_ports_type to join_node_base. We build the input port type + // using tuple_element. The class PortType is the port type (reserving_port, queueing_port, key_matching_port) + // and should match the typename. + template class PortType, typename OutputTuple, typename JoinPolicy> + class unfolded_join_node : public join_base::type { public: - typedef typename wrap_key_tuple_elements<8,key_matching_port,key_matching,OutputTuple>::type input_ports_type; - typedef OutputTuple output_type; + using input_ports_type = typename wrap_tuple_elements::type; + using output_type = OutputTuple; private: - typedef join_node_base , input_ports_type, output_type > base_type; - typedef type_to_key_function_body *f0_p; - typedef type_to_key_function_body *f1_p; - typedef type_to_key_function_body *f2_p; - typedef type_to_key_function_body *f3_p; - typedef type_to_key_function_body *f4_p; - typedef type_to_key_function_body *f5_p; - typedef type_to_key_function_body *f6_p; - typedef type_to_key_function_body *f7_p; - typedef std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p, f7_p > func_initializer_type; + using base_type = join_node_base; public: -#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING - unfolded_join_node(graph &g) : base_type(g, - func_initializer_type( - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()) - ) ) { - } -#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */ - template - unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4, - Body5 body5, Body6 body6, Body7 body7) : base_type(g, func_initializer_type( - new type_to_key_function_body_leaf(body0), - new type_to_key_function_body_leaf(body1), - new type_to_key_function_body_leaf(body2), - new type_to_key_function_body_leaf(body3), - new type_to_key_function_body_leaf(body4), - new type_to_key_function_body_leaf(body5), - new type_to_key_function_body_leaf(body6), - new type_to_key_function_body_leaf(body7) - ) ) { - static_assert(std::tuple_size::value == 8, "wrong number of body initializers"); - } + unfolded_join_node(graph& g) : base_type(g) {} unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} }; -#endif -#if __TBB_VARIADIC_MAX >= 9 - template - class unfolded_join_node<9,key_matching_port,OutputTuple,key_matching > : public - join_base<9,key_matching_port,OutputTuple,key_matching >::type { - typedef typename std::tuple_element<0, OutputTuple>::type T0; - typedef typename std::tuple_element<1, OutputTuple>::type T1; - typedef typename std::tuple_element<2, OutputTuple>::type T2; - typedef typename std::tuple_element<3, OutputTuple>::type T3; - typedef typename std::tuple_element<4, OutputTuple>::type T4; - typedef typename std::tuple_element<5, OutputTuple>::type T5; - typedef typename std::tuple_element<6, OutputTuple>::type T6; - typedef typename std::tuple_element<7, OutputTuple>::type T7; - typedef typename std::tuple_element<8, OutputTuple>::type T8; + // key_matching unfolded_join_node. This must be a separate specialization because the constructors + // differ. + template + class unfolded_join_node, key_matching> + : public join_base, key_matching>::type + { public: - typedef typename wrap_key_tuple_elements<9,key_matching_port,key_matching,OutputTuple>::type input_ports_type; - typedef OutputTuple output_type; + using input_ports_type = typename wrap_key_tuple_elements, + std::tuple>::type; + using output_type = std::tuple; private: - typedef join_node_base , input_ports_type, output_type > base_type; - typedef type_to_key_function_body *f0_p; - typedef type_to_key_function_body *f1_p; - typedef type_to_key_function_body *f2_p; - typedef type_to_key_function_body *f3_p; - typedef type_to_key_function_body *f4_p; - typedef type_to_key_function_body *f5_p; - typedef type_to_key_function_body *f6_p; - typedef type_to_key_function_body *f7_p; - typedef type_to_key_function_body *f8_p; - typedef std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p, f7_p, f8_p > func_initializer_type; + using base_type = join_node_base, input_ports_type, output_type>; + using func_initializer_type = std::tuple*...>; public: #if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING - unfolded_join_node(graph &g) : base_type(g, - func_initializer_type( - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()) - ) ) { - } -#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */ - template - unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4, - Body5 body5, Body6 body6, Body7 body7, Body8 body8) : base_type(g, func_initializer_type( - new type_to_key_function_body_leaf(body0), - new type_to_key_function_body_leaf(body1), - new type_to_key_function_body_leaf(body2), - new type_to_key_function_body_leaf(body3), - new type_to_key_function_body_leaf(body4), - new type_to_key_function_body_leaf(body5), - new type_to_key_function_body_leaf(body6), - new type_to_key_function_body_leaf(body7), - new type_to_key_function_body_leaf(body8) - ) ) { - static_assert(std::tuple_size::value == 9, "wrong number of body initializers"); - } - unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} - }; + unfolded_join_node(graph &g) : base_type(g, func_initializer_type( + new type_to_key_function_body_leaf> + (key_from_message_body())...)) + {} #endif - -#if __TBB_VARIADIC_MAX >= 10 - template - class unfolded_join_node<10,key_matching_port,OutputTuple,key_matching > : public - join_base<10,key_matching_port,OutputTuple,key_matching >::type { - typedef typename std::tuple_element<0, OutputTuple>::type T0; - typedef typename std::tuple_element<1, OutputTuple>::type T1; - typedef typename std::tuple_element<2, OutputTuple>::type T2; - typedef typename std::tuple_element<3, OutputTuple>::type T3; - typedef typename std::tuple_element<4, OutputTuple>::type T4; - typedef typename std::tuple_element<5, OutputTuple>::type T5; - typedef typename std::tuple_element<6, OutputTuple>::type T6; - typedef typename std::tuple_element<7, OutputTuple>::type T7; - typedef typename std::tuple_element<8, OutputTuple>::type T8; - typedef typename std::tuple_element<9, OutputTuple>::type T9; - public: - typedef typename wrap_key_tuple_elements<10,key_matching_port,key_matching,OutputTuple>::type input_ports_type; - typedef OutputTuple output_type; - private: - typedef join_node_base , input_ports_type, output_type > base_type; - typedef type_to_key_function_body *f0_p; - typedef type_to_key_function_body *f1_p; - typedef type_to_key_function_body *f2_p; - typedef type_to_key_function_body *f3_p; - typedef type_to_key_function_body *f4_p; - typedef type_to_key_function_body *f5_p; - typedef type_to_key_function_body *f6_p; - typedef type_to_key_function_body *f7_p; - typedef type_to_key_function_body *f8_p; - typedef type_to_key_function_body *f9_p; - typedef std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p, f7_p, f8_p, f9_p > func_initializer_type; - public: -#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING - unfolded_join_node(graph &g) : base_type(g, - func_initializer_type( - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()), - new type_to_key_function_body_leaf >(key_from_message_body()) - ) ) { - } -#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */ - template - unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4, - Body5 body5, Body6 body6, Body7 body7, Body8 body8, Body9 body9) : base_type(g, func_initializer_type( - new type_to_key_function_body_leaf(body0), - new type_to_key_function_body_leaf(body1), - new type_to_key_function_body_leaf(body2), - new type_to_key_function_body_leaf(body3), - new type_to_key_function_body_leaf(body4), - new type_to_key_function_body_leaf(body5), - new type_to_key_function_body_leaf(body6), - new type_to_key_function_body_leaf(body7), - new type_to_key_function_body_leaf(body8), - new type_to_key_function_body_leaf(body9) - ) ) { - static_assert(std::tuple_size::value == 10, "wrong number of body initializers"); - } + template + unfolded_join_node(graph &g, Bodies... bodies) : base_type(g, func_initializer_type( + new type_to_key_function_body_leaf(bodies)...)) + {} unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} }; -#endif //! templated function to refer to input ports of the join node template diff --git a/include/oneapi/tbb/detail/_flow_graph_types_impl.h b/include/oneapi/tbb/detail/_flow_graph_types_impl.h index e361b23e7b..df544027e1 100644 --- a/include/oneapi/tbb/detail/_flow_graph_types_impl.h +++ b/include/oneapi/tbb/detail/_flow_graph_types_impl.h @@ -1,5 +1,6 @@ /* - Copyright (c) 2005-2024 Intel Corporation + Copyright (c) 2005-2025 Intel Corporation + Copyright (c) 2025 UXL Foundation Contributors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -43,24 +44,24 @@ struct KeyTrait { }; // wrap each element of a tuple in a template, and make a tuple of the result. -template class PT, typename TypeTuple> +template class PortType, typename TypeTuple> struct wrap_tuple_elements; // A wrapper that generates the traits needed for each port of a key-matching join, // and the type of the tuple of input ports. -template class PT, typename KeyTraits, typename TypeTuple> +template class PortType, typename KeyTraits, typename TypeTuple> struct wrap_key_tuple_elements; -template class PT, typename... Args> -struct wrap_tuple_elements >{ - typedef typename std::tuple... > type; +template class PortType, typename... Args> +struct wrap_tuple_elements >{ + using type = std::tuple...>; }; -template class PT, typename KeyTraits, typename... Args> -struct wrap_key_tuple_elements > { - typedef typename KeyTraits::key_type K; - typedef typename KeyTraits::hash_compare_type KHash; - typedef typename std::tuple >... > type; +template class PortType, typename KeyTraits, typename... Args> +struct wrap_key_tuple_elements > { + using key_type = typename KeyTraits::key_type; + using hash_compare_type = typename KeyTraits::hash_compare_type; + using type = std::tuple>...>; }; template< int... S > class sequence {}; @@ -308,31 +309,11 @@ struct do_if { // the object can only be tested for type, and a read-only reference can be fetched by cast_to(). using tbb::detail::punned_cast; -struct tagged_null_type {}; -template -class tagged_msg { - typedef std::tuple= 6 - , T5 - #endif - #if __TBB_VARIADIC_MAX >= 7 - , T6 - #endif - #if __TBB_VARIADIC_MAX >= 8 - , T7 - #endif - #if __TBB_VARIADIC_MAX >= 9 - , T8 - #endif - #if __TBB_VARIADIC_MAX >= 10 - , T9 - #endif - > Tuple; -private: +template +class tagged_msg { + using Tuple = std::tuple; + class variant { static const size_t N = std::tuple_size::value; typedef typename pick_tuple_max::type AlignType; @@ -388,7 +369,6 @@ class tagged_msg { TagType my_tag; variant my_msg; - public: tagged_msg(): my_tag(TagType(~0)), my_msg(){} @@ -408,7 +388,7 @@ class tagged_msg { bool is_a() const {return my_msg.template variant_is_a();} bool is_default_constructed() const {return my_msg.variant_is_default_constructed();} -}; //class tagged_msg +}; // class tagged_msg // template to simplify cast and test for tagged_msg in template contexts template diff --git a/include/oneapi/tbb/flow_graph.h b/include/oneapi/tbb/flow_graph.h index 451ae2739b..efeb45a686 100644 --- a/include/oneapi/tbb/flow_graph.h +++ b/include/oneapi/tbb/flow_graph.h @@ -1,5 +1,6 @@ /* Copyright (c) 2005-2025 Intel Corporation + Copyright (c) 2025 UXL Foundation Contributors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -960,7 +961,7 @@ class function_node //! implements a function node that supports Input -> (set of outputs) // Output is a tuple of output types. -template +template __TBB_requires(std::default_initializable && std::copy_constructible) class multifunction_node : @@ -969,9 +970,8 @@ class multifunction_node : < Input, typename wrap_tuple_elements< - std::tuple_size::value, // #elements in tuple multifunction_output, // wrap this around each element - Output // the tuple providing the types + OutputTuple // Tuple with output types >::type, Policy, cache_aligned_allocator @@ -980,14 +980,14 @@ class multifunction_node : typedef cache_aligned_allocator internals_allocator; protected: - static const int N = std::tuple_size::value; + static const int N = std::tuple_size::value; public: - typedef Input input_type; - typedef null_type output_type; - typedef typename wrap_tuple_elements::type output_ports_type; - typedef multifunction_input< - input_type, output_ports_type, Policy, internals_allocator> input_impl_type; - typedef function_input_queue input_queue_type; + using input_type = Input; + using output_type = null_type; + using output_ports_type = typename wrap_tuple_elements::type; + using input_impl_type = + multifunction_input; + using input_queue_type = function_input_queue; private: using input_impl_type::my_predecessors; public: @@ -1045,7 +1045,6 @@ class split_node : public graph_node, public receiver { public: typedef TupleType input_type; typedef typename wrap_tuple_elements< - N, // #elements in tuple multifunction_output, // wrap this around each element TupleType // the tuple providing the types >::type output_ports_type; @@ -2413,10 +2412,10 @@ class limiter_node : public graph_node, public receiver< T >, public sender< T > template class join_node; template -class join_node: public unfolded_join_node::value, reserving_port, OutputTuple, reserving> { +class join_node: public unfolded_join_node { private: static const int N = std::tuple_size::value; - typedef unfolded_join_node unfolded_type; + using unfolded_type = unfolded_join_node; public: typedef OutputTuple output_type; typedef typename unfolded_type::input_ports_type input_ports_type; @@ -2440,10 +2439,10 @@ class join_node: public unfolded_join_node -class join_node: public unfolded_join_node::value, queueing_port, OutputTuple, queueing> { +class join_node: public unfolded_join_node { private: static const int N = std::tuple_size::value; - typedef unfolded_join_node unfolded_type; + using unfolded_type = unfolded_join_node; public: typedef OutputTuple output_type; typedef typename unfolded_type::input_ports_type input_ports_type; @@ -2485,11 +2484,10 @@ concept join_node_functions = requires { // template for key_matching join_node // tag_matching join_node is a specialization of key_matching, and is source-compatible. template -class join_node > : public unfolded_join_node::value, - key_matching_port, OutputTuple, key_matching > { +class join_node> : public unfolded_join_node> { private: static const int N = std::tuple_size::value; - typedef unfolded_join_node > unfolded_type; + using unfolded_type = unfolded_join_node>; public: typedef OutputTuple output_type; typedef typename unfolded_type::input_ports_type input_ports_type; @@ -2498,81 +2496,12 @@ class join_node > : public unfolded_join_nod join_node(graph &g) : unfolded_type(g) {} #endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */ - template - __TBB_requires(join_node_functions) - __TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1) : unfolded_type(g, b0, b1) { - fgt_multiinput_node( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - template - __TBB_requires(join_node_functions) - __TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2) : unfolded_type(g, b0, b1, b2) { - fgt_multiinput_node( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - template - __TBB_requires(join_node_functions) - __TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3) : unfolded_type(g, b0, b1, b2, b3) { - fgt_multiinput_node( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - template - __TBB_requires(join_node_functions) - __TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4) : - unfolded_type(g, b0, b1, b2, b3, b4) { - fgt_multiinput_node( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } -#if __TBB_VARIADIC_MAX >= 6 - template - __TBB_requires(join_node_functions) - __TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5) : - unfolded_type(g, b0, b1, b2, b3, b4, b5) { - fgt_multiinput_node( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } -#endif -#if __TBB_VARIADIC_MAX >= 7 - template - __TBB_requires(join_node_functions) - __TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6) : - unfolded_type(g, b0, b1, b2, b3, b4, b5, b6) { - fgt_multiinput_node( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } -#endif -#if __TBB_VARIADIC_MAX >= 8 - template - __TBB_requires(join_node_functions) - __TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6, - __TBB_B7 b7) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7) { - fgt_multiinput_node( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } -#endif -#if __TBB_VARIADIC_MAX >= 9 - template - __TBB_requires(join_node_functions) - __TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6, - __TBB_B7 b7, __TBB_B8 b8) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7, b8) { - fgt_multiinput_node( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } -#endif -#if __TBB_VARIADIC_MAX >= 10 - template - __TBB_requires(join_node_functions) - __TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6, - __TBB_B7 b7, __TBB_B8 b8, __TBB_B9 b9) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9) { + template > + __TBB_requires(join_node_functions) + __TBB_NOINLINE_SYM join_node(graph& g, Body body, Bodies... bodies) : unfolded_type(g, body, bodies...) { fgt_multiinput_node( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } -#endif #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET template < @@ -2599,191 +2528,16 @@ class join_node > : public unfolded_join_nod // indexer node #include "detail/_flow_graph_indexer_impl.h" -// TODO: Implement interface with variadic template or tuple -template class indexer_node; - -//indexer node specializations -template -class indexer_node : public unfolded_indexer_node > { -private: - static const int N = 1; -public: - typedef std::tuple InputTuple; - typedef tagged_msg output_type; - typedef unfolded_indexer_node unfolded_type; - __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET - template - indexer_node(const node_set& nodes) : indexer_node(nodes.graph_reference()) { - make_edges_in_order(nodes, *this); - } -#endif - - // Copy constructor - __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } -}; - -template -class indexer_node : public unfolded_indexer_node > { -private: - static const int N = 2; -public: - typedef std::tuple InputTuple; - typedef tagged_msg output_type; - typedef unfolded_indexer_node unfolded_type; - __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET - template - indexer_node(const node_set& nodes) : indexer_node(nodes.graph_reference()) { - make_edges_in_order(nodes, *this); - } -#endif - - // Copy constructor - __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -}; - -template -class indexer_node : public unfolded_indexer_node > { -private: - static const int N = 3; -public: - typedef std::tuple InputTuple; - typedef tagged_msg output_type; - typedef unfolded_indexer_node unfolded_type; - __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET - template - indexer_node(const node_set& nodes) : indexer_node(nodes.graph_reference()) { - make_edges_in_order(nodes, *this); - } -#endif - - // Copy constructor - __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -}; - -template -class indexer_node : public unfolded_indexer_node > { -private: - static const int N = 4; -public: - typedef std::tuple InputTuple; - typedef tagged_msg output_type; - typedef unfolded_indexer_node unfolded_type; - __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET - template - indexer_node(const node_set& nodes) : indexer_node(nodes.graph_reference()) { - make_edges_in_order(nodes, *this); - } -#endif - - // Copy constructor - __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -}; - -template -class indexer_node : public unfolded_indexer_node > { +template +__TBB_requires(std::copy_constructible && + (... && std::copy_constructible)) +class indexer_node : public unfolded_indexer_node { private: - static const int N = 5; + static constexpr std::size_t N = sizeof...(TN) + 1; public: - typedef std::tuple InputTuple; - typedef tagged_msg output_type; - typedef unfolded_indexer_node unfolded_type; - __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET - template - indexer_node(const node_set& nodes) : indexer_node(nodes.graph_reference()) { - make_edges_in_order(nodes, *this); - } -#endif - - // Copy constructor - __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -}; - -#if __TBB_VARIADIC_MAX >= 6 -template -class indexer_node : public unfolded_indexer_node > { -private: - static const int N = 6; -public: - typedef std::tuple InputTuple; - typedef tagged_msg output_type; - typedef unfolded_indexer_node unfolded_type; - __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } + using output_type = tagged_msg; + using unfolded_type = unfolded_indexer_node; -#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET - template - indexer_node(const node_set& nodes) : indexer_node(nodes.graph_reference()) { - make_edges_in_order(nodes, *this); - } -#endif - - // Copy constructor - __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -}; -#endif //variadic max 6 - -#if __TBB_VARIADIC_MAX >= 7 -template -class indexer_node : public unfolded_indexer_node > { -private: - static const int N = 7; -public: - typedef std::tuple InputTuple; - typedef tagged_msg output_type; - typedef unfolded_indexer_node unfolded_type; __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) { fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); @@ -2801,102 +2555,7 @@ class indexer_node : public unfolded_indexer_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } - -}; -#endif //variadic max 7 - -#if __TBB_VARIADIC_MAX >= 8 -template -class indexer_node : public unfolded_indexer_node > { -private: - static const int N = 8; -public: - typedef std::tuple InputTuple; - typedef tagged_msg output_type; - typedef unfolded_indexer_node unfolded_type; - indexer_node(graph& g) : unfolded_type(g) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET - template - indexer_node(const node_set& nodes) : indexer_node(nodes.graph_reference()) { - make_edges_in_order(nodes, *this); - } -#endif - - // Copy constructor - indexer_node( const indexer_node& other ) : unfolded_type(other) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -}; -#endif //variadic max 8 - -#if __TBB_VARIADIC_MAX >= 9 -template -class indexer_node : public unfolded_indexer_node > { -private: - static const int N = 9; -public: - typedef std::tuple InputTuple; - typedef tagged_msg output_type; - typedef unfolded_indexer_node unfolded_type; - __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET - template - indexer_node(const node_set& nodes) : indexer_node(nodes.graph_reference()) { - make_edges_in_order(nodes, *this); - } -#endif - - // Copy constructor - __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -}; -#endif //variadic max 9 - -#if __TBB_VARIADIC_MAX >= 10 -template -class indexer_node/*default*/ : public unfolded_indexer_node > { -private: - static const int N = 10; -public: - typedef std::tuple InputTuple; - typedef tagged_msg output_type; - typedef unfolded_indexer_node unfolded_type; - __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET - template - indexer_node(const node_set& nodes) : indexer_node(nodes.graph_reference()) { - make_edges_in_order(nodes, *this); - } -#endif - - // Copy constructor - __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) { - fgt_multiinput_node( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph, - this->input_ports(), static_cast< sender< output_type > *>(this) ); - } - -}; -#endif //variadic max 10 +}; // class indexer_node template< typename T > inline void internal_make_edge( sender &p, receiver &s ) { diff --git a/test/common/graph_utils.h b/test/common/graph_utils.h index 60b38b6df6..26a0c0ada0 100644 --- a/test/common/graph_utils.h +++ b/test/common/graph_utils.h @@ -1,5 +1,6 @@ /* Copyright (c) 2005-2025 Intel Corporation + Copyright (c) 2025 UXL Foundation Contributors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -970,4 +971,45 @@ void test(unsigned N) { } // namespace lightweight_testing +template +struct edge_maker { + template + static void make(Sender& sender, NodeType& node) { + oneapi::tbb::flow::make_edge(sender, oneapi::tbb::flow::input_port(node)); + edge_maker::make(sender, node); + } + + template + static void make(std::vector& senders, NodeType& node) { + oneapi::tbb::flow::make_edge(senders[N - 1], oneapi::tbb::flow::input_port(node)); + edge_maker::make(senders, node); + } +}; + +template <> +struct edge_maker<0> { + template + static void make(Sender&, NodeType&) {} +}; + +template +struct assert_all_items_equal_impl { + template + static void compare(const TupleLike& tuple_like, const Message& message) { + CHECK_MESSAGE(std::get(tuple_like) == message, "Unexpected element"); + assert_all_items_equal_impl::compare(tuple_like, message); + } +}; + +template <> +struct assert_all_items_equal_impl<0> { + template + static void compare(const TupleLike&, const Message&) {} +}; + +template +void assert_all_items_equal_to(const TupleLike& tuple_like, const Message& message) { + assert_all_items_equal_impl::value>::compare(tuple_like, message); +} + #endif // __TBB_harness_graph_H diff --git a/test/conformance/conformance_indexer_node.cpp b/test/conformance/conformance_indexer_node.cpp index 1cad744ed1..579a3007f0 100644 --- a/test/conformance/conformance_indexer_node.cpp +++ b/test/conformance/conformance_indexer_node.cpp @@ -1,5 +1,6 @@ /* - Copyright (c) 2020-2021 Intel Corporation + Copyright (c) 2020-2025 Intel Corporation + Copyright (c) 2025 UXL Foundation Contributors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,6 +20,7 @@ #endif #include "conformance_flowgraph.h" +#include //! \file conformance_indexer_node.cpp //! \brief Test for [flow_graph.indexer_node] specification @@ -161,3 +163,55 @@ TEST_CASE("indexer_node copy constructor"){ TEST_CASE("indexer_node output_type") { CHECK_MESSAGE((conformance::check_output_type>()), "indexer_node output_type should returns a tagged_msg"); } + +template +struct indexer_node_type_generator_impl { + using type = typename indexer_node_type_generator_impl::type; +}; + +template +struct indexer_node_type_generator_impl<0, Args...> { + using type = oneapi::tbb::flow::indexer_node; +}; + +// Generates oneapi::tbb::flow::indexer_node with N integer template arguments +template +using indexer_node_type_generator_t = typename indexer_node_type_generator_impl::type; + +template +void test_indexer_node_with_n_inputs() { + using namespace oneapi::tbb::flow; + using indexer_type = indexer_node_type_generator_t; + int message = 42; + + graph g; + + broadcast_node submitter(g); + indexer_type indexer(g); + + using output_type = typename indexer_type::output_type; + + std::unordered_set tags; + + function_node receiver(g, serial, [&](const output_type& indexer_output) { + auto result = tags.emplace(indexer_output.tag()); + CHECK_MESSAGE(result.second, "Duplicated tags returned from the indexer_node"); + CHECK_MESSAGE(cast_to(indexer_output) == message, "Invalid message returned from indexer node"); + }); + + edge_maker::make(submitter, indexer); + make_edge(indexer, receiver); + + submitter.try_put(message); + g.wait_for_all(); + + CHECK_MESSAGE(tags.size() == NInputs, "Incorrect number of tags returned from the indexer_node"); + for (std::size_t i = 0; i < NInputs; ++i) { + CHECK_MESSAGE(tags.count(i) == 1, "Some tag was not returned from indexer_node"); + } +} + +//! \brief \ref interface \ref requirement +TEST_CASE("indexer_node with large number of input ports") { + test_indexer_node_with_n_inputs<50>(); +} diff --git a/test/conformance/conformance_join_node.cpp b/test/conformance/conformance_join_node.cpp index 5262347134..78507d8786 100644 --- a/test/conformance/conformance_join_node.cpp +++ b/test/conformance/conformance_join_node.cpp @@ -1,5 +1,6 @@ /* - Copyright (c) 2020-2023 Intel Corporation + Copyright (c) 2020-2025 Intel Corporation + Copyright (c) 2025 UXL Foundation Contributors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -315,3 +316,86 @@ TEST_CASE("key_matching join_node invoke semantics") { test_invoke_basic(&test_invoke::SmartID::get_id_ref, &test_invoke::SmartID::get_id_ref); } #endif // __TBB_CPP17_INVOKE_PRESENT + +template +struct join_node_type_generator_impl { + using type = typename join_node_type_generator_impl::type; +}; + +template +struct join_node_type_generator_impl<0, JoinPolicy, Args...> { + using type = oneapi::tbb::flow::join_node, JoinPolicy>; +}; + +template +using join_node_type_generator_t = typename join_node_type_generator_impl::type; + +template +struct make_join_node_helper { + template + static join_node_type_generator_t make(oneapi::tbb::flow::graph& g, BodyToGenerate... body, Bodies... bodies) { + return make_join_node_helper::make(g, body..., bodies..., body...); + } +}; + +template +struct make_join_node_helper { + template + static join_node_type_generator_t make(oneapi::tbb::flow::graph& g, BodyToGenerate..., Bodies... bodies) { + return join_node_type_generator_t(g, bodies...); + } +}; + +template +join_node_type_generator_t make_join_node(oneapi::tbb::flow::graph& g, BodyToGenerate... body) { + return make_join_node_helper::make(g, body...); +} + +template +void test_join_node_with_n_inputs_impl(Body... body) { + static_assert(sizeof...(Body) <= 1, "Unexpected arguments"); + + using namespace oneapi::tbb::flow; + using join_node_type = join_node_type_generator_t; + graph g; + int message = 42; + + broadcast_node submitter(g); + + // A set of buffers between each input port for reserving policy + std::vector> buffers(N, buffer_node{g}); + + join_node_type join = make_join_node(g, body...); + + using output_tuple = typename join_node_type::output_type; + + std::size_t body_counter = 0; + function_node function(g, serial, [&](const output_tuple& tuple) { + assert_all_items_equal_to(tuple, message); + ++body_counter; + }); + + for (auto& buffer : buffers) { + make_edge(submitter, buffer); + } + edge_maker::make(buffers, join); + oneapi::tbb::flow::make_edge(join, function); + + submitter.try_put(message); + g.wait_for_all(); + + CHECK_MESSAGE(body_counter == 1, "Unexpected number of body calls"); +} + +template +void test_join_node_with_n_inputs() { + test_join_node_with_n_inputs_impl(); + test_join_node_with_n_inputs_impl(); + test_join_node_with_n_inputs_impl, N>([](int) { return 0; }); + test_join_node_with_n_inputs_impl([](oneapi::tbb::flow::tag_value) { return 0; }); +} + +//! \brief \ref interface \ref requirement +TEST_CASE("join_node with large number of input ports") { + test_join_node_with_n_inputs<50>(); +}