Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-30 08:46:17

0001 /*
0002     Copyright (c) 2020-2021 Intel Corporation
0003 
0004     Licensed under the Apache License, Version 2.0 (the "License");
0005     you may not use this file except in compliance with the License.
0006     You may obtain a copy of the License at
0007 
0008         http://www.apache.org/licenses/LICENSE-2.0
0009 
0010     Unless required by applicable law or agreed to in writing, software
0011     distributed under the License is distributed on an "AS IS" BASIS,
0012     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013     See the License for the specific language governing permissions and
0014     limitations under the License.
0015 */
0016 
0017 #ifndef __TBB_flow_graph_node_set_impl_H
0018 #define __TBB_flow_graph_node_set_impl_H
0019 
0020 #ifndef __TBB_flow_graph_H
0021 #error Do not #include this internal file directly; use public TBB headers instead.
0022 #endif
0023 
0024 // Included in namespace tbb::detail::d1 (in flow_graph.h)
0025 
0026 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
0027 // Visual Studio 2019 reports an error while calling predecessor_selector::get and successor_selector::get
0028 // Seems like the well-formed expression in trailing decltype is treated as ill-formed
0029 // TODO: investigate problems with decltype in trailing return types or find the cross-platform solution
0030 #define __TBB_MSVC_DISABLE_TRAILING_DECLTYPE (_MSC_VER >= 1900)
0031 
0032 namespace order {
0033 struct undefined {};
0034 struct following {};
0035 struct preceding {};
0036 }
0037 
0038 class get_graph_helper {
0039 public:
0040     // TODO: consider making graph_reference() public and consistent interface to get a reference to the graph
0041     // and remove get_graph_helper
0042     template <typename T>
0043     static graph& get(const T& object) {
0044         return get_impl(object, std::is_base_of<graph_node, T>());
0045     }
0046 
0047 private:
0048     // Get graph from the object of type derived from graph_node
0049     template <typename T>
0050     static graph& get_impl(const T& object, std::true_type) {
0051         return static_cast<const graph_node*>(&object)->my_graph;
0052     }
0053 
0054     template <typename T>
0055     static graph& get_impl(const T& object, std::false_type) {
0056         return object.graph_reference();
0057     }
0058 };
0059 
0060 template<typename Order, typename... Nodes>
0061 struct node_set {
0062     typedef Order order_type;
0063 
0064     std::tuple<Nodes&...> nodes;
0065     node_set(Nodes&... ns) : nodes(ns...) {}
0066 
0067     template <typename... Nodes2>
0068     node_set(const node_set<order::undefined, Nodes2...>& set) : nodes(set.nodes) {}
0069 
0070     graph& graph_reference() const {
0071         return get_graph_helper::get(std::get<0>(nodes));
0072     }
0073 };
0074 
0075 namespace alias_helpers {
0076 template <typename T> using output_type = typename T::output_type;
0077 template <typename T> using output_ports_type = typename T::output_ports_type;
0078 template <typename T> using input_type = typename T::input_type;
0079 template <typename T> using input_ports_type = typename T::input_ports_type;
0080 } // namespace alias_helpers
0081 
0082 template <typename T>
0083 using has_output_type = supports<T, alias_helpers::output_type>;
0084 
0085 template <typename T>
0086 using has_input_type = supports<T, alias_helpers::input_type>;
0087 
0088 template <typename T>
0089 using has_input_ports_type = supports<T, alias_helpers::input_ports_type>;
0090 
0091 template <typename T>
0092 using has_output_ports_type = supports<T, alias_helpers::output_ports_type>;
0093 
0094 template<typename T>
0095 struct is_sender : std::is_base_of<sender<typename T::output_type>, T> {};
0096 
0097 template<typename T>
0098 struct is_receiver : std::is_base_of<receiver<typename T::input_type>, T> {};
0099 
0100 template <typename Node>
0101 struct is_async_node : std::false_type {};
0102 
0103 template <typename... Args>
0104 struct is_async_node<async_node<Args...>> : std::true_type {};
0105 
0106 template<typename FirstPredecessor, typename... Predecessors>
0107 node_set<order::following, FirstPredecessor, Predecessors...>
0108 follows(FirstPredecessor& first_predecessor, Predecessors&... predecessors) {
0109     static_assert((conjunction<has_output_type<FirstPredecessor>,
0110                                                    has_output_type<Predecessors>...>::value),
0111                         "Not all node's predecessors has output_type typedef");
0112     static_assert((conjunction<is_sender<FirstPredecessor>, is_sender<Predecessors>...>::value),
0113                         "Not all node's predecessors are senders");
0114     return node_set<order::following, FirstPredecessor, Predecessors...>(first_predecessor, predecessors...);
0115 }
0116 
0117 template<typename... Predecessors>
0118 node_set<order::following, Predecessors...>
0119 follows(node_set<order::undefined, Predecessors...>& predecessors_set) {
0120     static_assert((conjunction<has_output_type<Predecessors>...>::value),
0121                         "Not all nodes in the set has output_type typedef");
0122     static_assert((conjunction<is_sender<Predecessors>...>::value),
0123                         "Not all nodes in the set are senders");
0124     return node_set<order::following, Predecessors...>(predecessors_set);
0125 }
0126 
0127 template<typename FirstSuccessor, typename... Successors>
0128 node_set<order::preceding, FirstSuccessor, Successors...>
0129 precedes(FirstSuccessor& first_successor, Successors&... successors) {
0130     static_assert((conjunction<has_input_type<FirstSuccessor>,
0131                                                     has_input_type<Successors>...>::value),
0132                         "Not all node's successors has input_type typedef");
0133     static_assert((conjunction<is_receiver<FirstSuccessor>, is_receiver<Successors>...>::value),
0134                         "Not all node's successors are receivers");
0135     return node_set<order::preceding, FirstSuccessor, Successors...>(first_successor, successors...);
0136 }
0137 
0138 template<typename... Successors>
0139 node_set<order::preceding, Successors...>
0140 precedes(node_set<order::undefined, Successors...>& successors_set) {
0141     static_assert((conjunction<has_input_type<Successors>...>::value),
0142                         "Not all nodes in the set has input_type typedef");
0143     static_assert((conjunction<is_receiver<Successors>...>::value),
0144                         "Not all nodes in the set are receivers");
0145     return node_set<order::preceding, Successors...>(successors_set);
0146 }
0147 
0148 template <typename Node, typename... Nodes>
0149 node_set<order::undefined, Node, Nodes...>
0150 make_node_set(Node& first_node, Nodes&... nodes) {
0151     return node_set<order::undefined, Node, Nodes...>(first_node, nodes...);
0152 }
0153 
0154 template<size_t I>
0155 class successor_selector {
0156     template <typename NodeType>
0157     static auto get_impl(NodeType& node, std::true_type) -> decltype(input_port<I>(node)) {
0158         return input_port<I>(node);
0159     }
0160 
0161     template <typename NodeType>
0162     static NodeType& get_impl(NodeType& node, std::false_type) { return node; }
0163 
0164 public:
0165     template <typename NodeType>
0166 #if __TBB_MSVC_DISABLE_TRAILING_DECLTYPE
0167     static auto& get(NodeType& node)
0168 #else
0169     static auto get(NodeType& node) -> decltype(get_impl(node, has_input_ports_type<NodeType>()))
0170 #endif
0171     {
0172         return get_impl(node, has_input_ports_type<NodeType>());
0173     }
0174 };
0175 
0176 template<size_t I>
0177 class predecessor_selector {
0178     template <typename NodeType>
0179     static auto internal_get(NodeType& node, std::true_type) -> decltype(output_port<I>(node)) {
0180         return output_port<I>(node);
0181     }
0182 
0183     template <typename NodeType>
0184     static NodeType& internal_get(NodeType& node, std::false_type) { return node;}
0185 
0186     template <typename NodeType>
0187 #if __TBB_MSVC_DISABLE_TRAILING_DECLTYPE
0188     static auto& get_impl(NodeType& node, std::false_type)
0189 #else
0190     static auto get_impl(NodeType& node, std::false_type) -> decltype(internal_get(node, has_output_ports_type<NodeType>()))
0191 #endif
0192     {
0193         return internal_get(node, has_output_ports_type<NodeType>());
0194     }
0195 
0196     template <typename AsyncNode>
0197     static AsyncNode& get_impl(AsyncNode& node, std::true_type) { return node; }
0198 
0199 public:
0200     template <typename NodeType>
0201 #if __TBB_MSVC_DISABLE_TRAILING_DECLTYPE
0202     static auto& get(NodeType& node)
0203 #else
0204     static auto get(NodeType& node) -> decltype(get_impl(node, is_async_node<NodeType>()))
0205 #endif
0206     {
0207         return get_impl(node, is_async_node<NodeType>());
0208     }
0209 };
0210 
0211 template<size_t I>
0212 class make_edges_helper {
0213 public:
0214     template<typename PredecessorsTuple, typename NodeType>
0215     static void connect_predecessors(PredecessorsTuple& predecessors, NodeType& node) {
0216         make_edge(std::get<I>(predecessors), successor_selector<I>::get(node));
0217         make_edges_helper<I - 1>::connect_predecessors(predecessors, node);
0218     }
0219 
0220     template<typename SuccessorsTuple, typename NodeType>
0221     static void connect_successors(NodeType& node, SuccessorsTuple& successors) {
0222         make_edge(predecessor_selector<I>::get(node), std::get<I>(successors));
0223         make_edges_helper<I - 1>::connect_successors(node, successors);
0224     }
0225 };
0226 
0227 template<>
0228 struct make_edges_helper<0> {
0229     template<typename PredecessorsTuple, typename NodeType>
0230     static void connect_predecessors(PredecessorsTuple& predecessors, NodeType& node) {
0231         make_edge(std::get<0>(predecessors), successor_selector<0>::get(node));
0232     }
0233 
0234     template<typename SuccessorsTuple, typename NodeType>
0235     static void connect_successors(NodeType& node, SuccessorsTuple& successors) {
0236         make_edge(predecessor_selector<0>::get(node), std::get<0>(successors));
0237     }
0238 };
0239 
0240 // TODO: consider adding an overload for making edges between node sets
0241 template<typename NodeType, typename OrderFlagType, typename... Args>
0242 void make_edges(const node_set<OrderFlagType, Args...>& s, NodeType& node) {
0243     const std::size_t SetSize = std::tuple_size<decltype(s.nodes)>::value;
0244     make_edges_helper<SetSize - 1>::connect_predecessors(s.nodes, node);
0245 }
0246 
0247 template <typename NodeType, typename OrderFlagType, typename... Args>
0248 void make_edges(NodeType& node, const node_set<OrderFlagType, Args...>& s) {
0249     const std::size_t SetSize = std::tuple_size<decltype(s.nodes)>::value;
0250     make_edges_helper<SetSize - 1>::connect_successors(node, s.nodes);
0251 }
0252 
0253 template <typename NodeType, typename... Nodes>
0254 void make_edges_in_order(const node_set<order::following, Nodes...>& ns, NodeType& node) {
0255     make_edges(ns, node);
0256 }
0257 
0258 template <typename NodeType, typename... Nodes>
0259 void make_edges_in_order(const node_set<order::preceding, Nodes...>& ns, NodeType& node) {
0260     make_edges(node, ns);
0261 }
0262 
0263 #endif  // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
0264 
0265 #endif // __TBB_flow_graph_node_set_impl_H