File indexing completed on 2025-01-18 10:12:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
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
0025
0026 namespace internal {
0027
0028 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
0029
0030
0031
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
0043
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
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 }
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
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
0266
0267 }
0268
0269 #endif