Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:12:48

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