149e08aacStbbdev /* 2*b15aabb3Stbbdev Copyright (c) 2020-2021 Intel Corporation 349e08aacStbbdev 449e08aacStbbdev Licensed under the Apache License, Version 2.0 (the "License"); 549e08aacStbbdev you may not use this file except in compliance with the License. 649e08aacStbbdev You may obtain a copy of the License at 749e08aacStbbdev 849e08aacStbbdev http://www.apache.org/licenses/LICENSE-2.0 949e08aacStbbdev 1049e08aacStbbdev Unless required by applicable law or agreed to in writing, software 1149e08aacStbbdev distributed under the License is distributed on an "AS IS" BASIS, 1249e08aacStbbdev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1349e08aacStbbdev See the License for the specific language governing permissions and 1449e08aacStbbdev limitations under the License. 1549e08aacStbbdev */ 1649e08aacStbbdev 1749e08aacStbbdev #ifndef __TBB_flow_graph_node_set_impl_H 1849e08aacStbbdev #define __TBB_flow_graph_node_set_impl_H 1949e08aacStbbdev 2049e08aacStbbdev #ifndef __TBB_flow_graph_H 2149e08aacStbbdev #error Do not #include this internal file directly; use public TBB headers instead. 2249e08aacStbbdev #endif 2349e08aacStbbdev 2449e08aacStbbdev // Included in namespace tbb::detail::d1 (in flow_graph.h) 2549e08aacStbbdev 2649e08aacStbbdev #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET 2749e08aacStbbdev // Visual Studio 2019 reports an error while calling predecessor_selector::get and successor_selector::get 2849e08aacStbbdev // Seems like the well-formed expression in trailing decltype is treated as ill-formed 2949e08aacStbbdev // TODO: investigate problems with decltype in trailing return types or find the cross-platform solution 3049e08aacStbbdev #define __TBB_MSVC_DISABLE_TRAILING_DECLTYPE (_MSC_VER >= 1900) 3149e08aacStbbdev 3249e08aacStbbdev namespace order { 3349e08aacStbbdev struct undefined {}; 3449e08aacStbbdev struct following {}; 3549e08aacStbbdev struct preceding {}; 3649e08aacStbbdev } 3749e08aacStbbdev 3849e08aacStbbdev class get_graph_helper { 3949e08aacStbbdev public: 4049e08aacStbbdev // TODO: consider making graph_reference() public and consistent interface to get a reference to the graph 4149e08aacStbbdev // and remove get_graph_helper 4249e08aacStbbdev template <typename T> get(const T & object)4349e08aacStbbdev static graph& get(const T& object) { 4449e08aacStbbdev return get_impl(object, std::is_base_of<graph_node, T>()); 4549e08aacStbbdev } 4649e08aacStbbdev 4749e08aacStbbdev private: 4849e08aacStbbdev // Get graph from the object of type derived from graph_node 4949e08aacStbbdev template <typename T> get_impl(const T & object,std::true_type)5049e08aacStbbdev static graph& get_impl(const T& object, std::true_type) { 5149e08aacStbbdev return static_cast<const graph_node*>(&object)->my_graph; 5249e08aacStbbdev } 5349e08aacStbbdev 5449e08aacStbbdev template <typename T> get_impl(const T & object,std::false_type)5549e08aacStbbdev static graph& get_impl(const T& object, std::false_type) { 5649e08aacStbbdev return object.graph_reference(); 5749e08aacStbbdev } 5849e08aacStbbdev }; 5949e08aacStbbdev 6049e08aacStbbdev template<typename Order, typename... Nodes> 6149e08aacStbbdev struct node_set { 6249e08aacStbbdev typedef Order order_type; 6349e08aacStbbdev 6449e08aacStbbdev std::tuple<Nodes&...> nodes; node_setnode_set6549e08aacStbbdev node_set(Nodes&... ns) : nodes(ns...) {} 6649e08aacStbbdev 6749e08aacStbbdev template <typename... Nodes2> node_setnode_set6849e08aacStbbdev node_set(const node_set<order::undefined, Nodes2...>& set) : nodes(set.nodes) {} 6949e08aacStbbdev graph_referencenode_set7049e08aacStbbdev graph& graph_reference() const { 7149e08aacStbbdev return get_graph_helper::get(std::get<0>(nodes)); 7249e08aacStbbdev } 7349e08aacStbbdev }; 7449e08aacStbbdev 7549e08aacStbbdev namespace alias_helpers { 7649e08aacStbbdev template <typename T> using output_type = typename T::output_type; 7749e08aacStbbdev template <typename T> using output_ports_type = typename T::output_ports_type; 7849e08aacStbbdev template <typename T> using input_type = typename T::input_type; 7949e08aacStbbdev template <typename T> using input_ports_type = typename T::input_ports_type; 8049e08aacStbbdev } // namespace alias_helpers 8149e08aacStbbdev 8249e08aacStbbdev template <typename T> 8349e08aacStbbdev using has_output_type = supports<T, alias_helpers::output_type>; 8449e08aacStbbdev 8549e08aacStbbdev template <typename T> 8649e08aacStbbdev using has_input_type = supports<T, alias_helpers::input_type>; 8749e08aacStbbdev 8849e08aacStbbdev template <typename T> 8949e08aacStbbdev using has_input_ports_type = supports<T, alias_helpers::input_ports_type>; 9049e08aacStbbdev 9149e08aacStbbdev template <typename T> 9249e08aacStbbdev using has_output_ports_type = supports<T, alias_helpers::output_ports_type>; 9349e08aacStbbdev 9449e08aacStbbdev template<typename T> 9549e08aacStbbdev struct is_sender : std::is_base_of<sender<typename T::output_type>, T> {}; 9649e08aacStbbdev 9749e08aacStbbdev template<typename T> 9849e08aacStbbdev struct is_receiver : std::is_base_of<receiver<typename T::input_type>, T> {}; 9949e08aacStbbdev 10049e08aacStbbdev template <typename Node> 10149e08aacStbbdev struct is_async_node : std::false_type {}; 10249e08aacStbbdev 10349e08aacStbbdev template <typename... Args> 10449e08aacStbbdev struct is_async_node<async_node<Args...>> : std::true_type {}; 10549e08aacStbbdev 10649e08aacStbbdev template<typename FirstPredecessor, typename... Predecessors> 10749e08aacStbbdev node_set<order::following, FirstPredecessor, Predecessors...> 10849e08aacStbbdev follows(FirstPredecessor& first_predecessor, Predecessors&... predecessors) { 10949e08aacStbbdev static_assert((conjunction<has_output_type<FirstPredecessor>, 11049e08aacStbbdev has_output_type<Predecessors>...>::value), 11149e08aacStbbdev "Not all node's predecessors has output_type typedef"); 11249e08aacStbbdev static_assert((conjunction<is_sender<FirstPredecessor>, is_sender<Predecessors>...>::value), 11349e08aacStbbdev "Not all node's predecessors are senders"); 11449e08aacStbbdev return node_set<order::following, FirstPredecessor, Predecessors...>(first_predecessor, predecessors...); 11549e08aacStbbdev } 11649e08aacStbbdev 11749e08aacStbbdev template<typename... Predecessors> 11849e08aacStbbdev node_set<order::following, Predecessors...> 11949e08aacStbbdev follows(node_set<order::undefined, Predecessors...>& predecessors_set) { 12049e08aacStbbdev static_assert((conjunction<has_output_type<Predecessors>...>::value), 12149e08aacStbbdev "Not all nodes in the set has output_type typedef"); 12249e08aacStbbdev static_assert((conjunction<is_sender<Predecessors>...>::value), 12349e08aacStbbdev "Not all nodes in the set are senders"); 12449e08aacStbbdev return node_set<order::following, Predecessors...>(predecessors_set); 12549e08aacStbbdev } 12649e08aacStbbdev 12749e08aacStbbdev template<typename FirstSuccessor, typename... Successors> 12849e08aacStbbdev node_set<order::preceding, FirstSuccessor, Successors...> 12949e08aacStbbdev precedes(FirstSuccessor& first_successor, Successors&... successors) { 13049e08aacStbbdev static_assert((conjunction<has_input_type<FirstSuccessor>, 13149e08aacStbbdev has_input_type<Successors>...>::value), 13249e08aacStbbdev "Not all node's successors has input_type typedef"); 13349e08aacStbbdev static_assert((conjunction<is_receiver<FirstSuccessor>, is_receiver<Successors>...>::value), 13449e08aacStbbdev "Not all node's successors are receivers"); 13549e08aacStbbdev return node_set<order::preceding, FirstSuccessor, Successors...>(first_successor, successors...); 13649e08aacStbbdev } 13749e08aacStbbdev 13849e08aacStbbdev template<typename... Successors> 13949e08aacStbbdev node_set<order::preceding, Successors...> 14049e08aacStbbdev precedes(node_set<order::undefined, Successors...>& successors_set) { 14149e08aacStbbdev static_assert((conjunction<has_input_type<Successors>...>::value), 14249e08aacStbbdev "Not all nodes in the set has input_type typedef"); 14349e08aacStbbdev static_assert((conjunction<is_receiver<Successors>...>::value), 14449e08aacStbbdev "Not all nodes in the set are receivers"); 14549e08aacStbbdev return node_set<order::preceding, Successors...>(successors_set); 14649e08aacStbbdev } 14749e08aacStbbdev 14849e08aacStbbdev template <typename Node, typename... Nodes> 14949e08aacStbbdev node_set<order::undefined, Node, Nodes...> 15049e08aacStbbdev make_node_set(Node& first_node, Nodes&... nodes) { 15149e08aacStbbdev return node_set<order::undefined, Node, Nodes...>(first_node, nodes...); 15249e08aacStbbdev } 15349e08aacStbbdev 15449e08aacStbbdev template<size_t I> 15549e08aacStbbdev class successor_selector { 15649e08aacStbbdev template <typename NodeType> 15749e08aacStbbdev static auto get_impl(NodeType& node, std::true_type) -> decltype(input_port<I>(node)) { 15849e08aacStbbdev return input_port<I>(node); 15949e08aacStbbdev } 16049e08aacStbbdev 16149e08aacStbbdev template <typename NodeType> 16249e08aacStbbdev static NodeType& get_impl(NodeType& node, std::false_type) { return node; } 16349e08aacStbbdev 16449e08aacStbbdev public: 16549e08aacStbbdev template <typename NodeType> 16649e08aacStbbdev #if __TBB_MSVC_DISABLE_TRAILING_DECLTYPE 16749e08aacStbbdev static auto& get(NodeType& node) 16849e08aacStbbdev #else 16949e08aacStbbdev static auto get(NodeType& node) -> decltype(get_impl(node, has_input_ports_type<NodeType>())) 17049e08aacStbbdev #endif 17149e08aacStbbdev { 17249e08aacStbbdev return get_impl(node, has_input_ports_type<NodeType>()); 17349e08aacStbbdev } 17449e08aacStbbdev }; 17549e08aacStbbdev 17649e08aacStbbdev template<size_t I> 17749e08aacStbbdev class predecessor_selector { 17849e08aacStbbdev template <typename NodeType> 17949e08aacStbbdev static auto internal_get(NodeType& node, std::true_type) -> decltype(output_port<I>(node)) { 18049e08aacStbbdev return output_port<I>(node); 18149e08aacStbbdev } 18249e08aacStbbdev 18349e08aacStbbdev template <typename NodeType> 18449e08aacStbbdev static NodeType& internal_get(NodeType& node, std::false_type) { return node;} 18549e08aacStbbdev 18649e08aacStbbdev template <typename NodeType> 18749e08aacStbbdev #if __TBB_MSVC_DISABLE_TRAILING_DECLTYPE 18849e08aacStbbdev static auto& get_impl(NodeType& node, std::false_type) 18949e08aacStbbdev #else 19049e08aacStbbdev static auto get_impl(NodeType& node, std::false_type) -> decltype(internal_get(node, has_output_ports_type<NodeType>())) 19149e08aacStbbdev #endif 19249e08aacStbbdev { 19349e08aacStbbdev return internal_get(node, has_output_ports_type<NodeType>()); 19449e08aacStbbdev } 19549e08aacStbbdev 19649e08aacStbbdev template <typename AsyncNode> 19749e08aacStbbdev static AsyncNode& get_impl(AsyncNode& node, std::true_type) { return node; } 19849e08aacStbbdev 19949e08aacStbbdev public: 20049e08aacStbbdev template <typename NodeType> 20149e08aacStbbdev #if __TBB_MSVC_DISABLE_TRAILING_DECLTYPE 20249e08aacStbbdev static auto& get(NodeType& node) 20349e08aacStbbdev #else 20449e08aacStbbdev static auto get(NodeType& node) -> decltype(get_impl(node, is_async_node<NodeType>())) 20549e08aacStbbdev #endif 20649e08aacStbbdev { 20749e08aacStbbdev return get_impl(node, is_async_node<NodeType>()); 20849e08aacStbbdev } 20949e08aacStbbdev }; 21049e08aacStbbdev 21149e08aacStbbdev template<size_t I> 21249e08aacStbbdev class make_edges_helper { 21349e08aacStbbdev public: 21449e08aacStbbdev template<typename PredecessorsTuple, typename NodeType> 21549e08aacStbbdev static void connect_predecessors(PredecessorsTuple& predecessors, NodeType& node) { 21649e08aacStbbdev make_edge(std::get<I>(predecessors), successor_selector<I>::get(node)); 21749e08aacStbbdev make_edges_helper<I - 1>::connect_predecessors(predecessors, node); 21849e08aacStbbdev } 21949e08aacStbbdev 22049e08aacStbbdev template<typename SuccessorsTuple, typename NodeType> 22149e08aacStbbdev static void connect_successors(NodeType& node, SuccessorsTuple& successors) { 22249e08aacStbbdev make_edge(predecessor_selector<I>::get(node), std::get<I>(successors)); 22349e08aacStbbdev make_edges_helper<I - 1>::connect_successors(node, successors); 22449e08aacStbbdev } 22549e08aacStbbdev }; 22649e08aacStbbdev 22749e08aacStbbdev template<> 22849e08aacStbbdev struct make_edges_helper<0> { 22949e08aacStbbdev template<typename PredecessorsTuple, typename NodeType> 23049e08aacStbbdev static void connect_predecessors(PredecessorsTuple& predecessors, NodeType& node) { 23149e08aacStbbdev make_edge(std::get<0>(predecessors), successor_selector<0>::get(node)); 23249e08aacStbbdev } 23349e08aacStbbdev 23449e08aacStbbdev template<typename SuccessorsTuple, typename NodeType> 23549e08aacStbbdev static void connect_successors(NodeType& node, SuccessorsTuple& successors) { 23649e08aacStbbdev make_edge(predecessor_selector<0>::get(node), std::get<0>(successors)); 23749e08aacStbbdev } 23849e08aacStbbdev }; 23949e08aacStbbdev 24049e08aacStbbdev // TODO: consider adding an overload for making edges between node sets 24149e08aacStbbdev template<typename NodeType, typename OrderFlagType, typename... Args> 24249e08aacStbbdev void make_edges(const node_set<OrderFlagType, Args...>& s, NodeType& node) { 24349e08aacStbbdev const std::size_t SetSize = std::tuple_size<decltype(s.nodes)>::value; 24449e08aacStbbdev make_edges_helper<SetSize - 1>::connect_predecessors(s.nodes, node); 24549e08aacStbbdev } 24649e08aacStbbdev 24749e08aacStbbdev template <typename NodeType, typename OrderFlagType, typename... Args> 24849e08aacStbbdev void make_edges(NodeType& node, const node_set<OrderFlagType, Args...>& s) { 24949e08aacStbbdev const std::size_t SetSize = std::tuple_size<decltype(s.nodes)>::value; 25049e08aacStbbdev make_edges_helper<SetSize - 1>::connect_successors(node, s.nodes); 25149e08aacStbbdev } 25249e08aacStbbdev 25349e08aacStbbdev template <typename NodeType, typename... Nodes> 25449e08aacStbbdev void make_edges_in_order(const node_set<order::following, Nodes...>& ns, NodeType& node) { 25549e08aacStbbdev make_edges(ns, node); 25649e08aacStbbdev } 25749e08aacStbbdev 25849e08aacStbbdev template <typename NodeType, typename... Nodes> 25949e08aacStbbdev void make_edges_in_order(const node_set<order::preceding, Nodes...>& ns, NodeType& node) { 26049e08aacStbbdev make_edges(node, ns); 26149e08aacStbbdev } 26249e08aacStbbdev 26349e08aacStbbdev #endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET 26449e08aacStbbdev 26549e08aacStbbdev #endif // __TBB_flow_graph_node_set_impl_H 266