File indexing completed on 2025-07-30 08:46:17
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 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
0027
0028
0029
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
0041
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
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 }
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
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
0264
0265 #endif