| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- /*
- Copyright (c) 2019-2020 Intel Corporation
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- #ifndef __TBB_flow_graph_node_set_impl_H
- #define __TBB_flow_graph_node_set_impl_H
- #ifndef __TBB_flow_graph_H
- #error Do not #include this internal file directly; use public TBB headers instead.
- #endif
- // Included in namespace tbb::flow::interfaceX (in flow_graph.h)
- namespace internal {
- #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
- // Visual Studio 2019 reports an error while calling predecessor_selector::get and successor_selector::get
- // Seems like the well-formed expression in trailing decltype is treated as ill-formed
- // TODO: investigate problems with decltype in trailing return types or find the cross-platform solution
- #define __TBB_MSVC_DISABLE_TRAILING_DECLTYPE (_MSC_VER >= 1900)
- namespace order {
- struct undefined {};
- struct following {};
- struct preceding {};
- }
- class get_graph_helper {
- public:
- // TODO: consider making graph_reference() public and consistent interface to get a reference to the graph
- // and remove get_graph_helper
- template <typename T>
- static graph& get(const T& object) {
- return get_impl(object, std::is_base_of<graph_node, T>());
- }
- private:
- // Get graph from the object of type derived from graph_node
- template <typename T>
- static graph& get_impl(const T& object, std::true_type) {
- return static_cast<const graph_node*>(&object)->my_graph;
- }
- template <typename T>
- static graph& get_impl(const T& object, std::false_type) {
- return object.graph_reference();
- }
- };
- template<typename Order, typename... Nodes>
- struct node_set {
- typedef Order order_type;
- tbb::flow::tuple<Nodes&...> nodes;
- node_set(Nodes&... ns) : nodes(ns...) {}
- template <typename... Nodes2>
- node_set(const node_set<order::undefined, Nodes2...>& set) : nodes(set.nodes) {}
- graph& graph_reference() const {
- return get_graph_helper::get(std::get<0>(nodes));
- }
- };
- namespace alias_helpers {
- template <typename T> using output_type = typename T::output_type;
- template <typename T> using output_ports_type = typename T::output_ports_type;
- template <typename T> using input_type = typename T::input_type;
- template <typename T> using input_ports_type = typename T::input_ports_type;
- } // namespace alias_helpers
- template <typename T>
- using has_output_type = tbb::internal::supports<T, alias_helpers::output_type>;
- template <typename T>
- using has_input_type = tbb::internal::supports<T, alias_helpers::input_type>;
- template <typename T>
- using has_input_ports_type = tbb::internal::supports<T, alias_helpers::input_ports_type>;
- template <typename T>
- using has_output_ports_type = tbb::internal::supports<T, alias_helpers::output_ports_type>;
- template<typename T>
- struct is_sender : std::is_base_of<sender<typename T::output_type>, T> {};
- template<typename T>
- struct is_receiver : std::is_base_of<receiver<typename T::input_type>, T> {};
- template <typename Node>
- struct is_async_node : std::false_type {};
- template <typename... Args>
- struct is_async_node<tbb::flow::interface11::async_node<Args...>> : std::true_type {};
- template<typename FirstPredecessor, typename... Predecessors>
- node_set<order::following, FirstPredecessor, Predecessors...>
- follows(FirstPredecessor& first_predecessor, Predecessors&... predecessors) {
- __TBB_STATIC_ASSERT((tbb::internal::conjunction<has_output_type<FirstPredecessor>,
- has_output_type<Predecessors>...>::value),
- "Not all node's predecessors has output_type typedef");
- __TBB_STATIC_ASSERT((tbb::internal::conjunction<is_sender<FirstPredecessor>, is_sender<Predecessors>...>::value),
- "Not all node's predecessors are senders");
- return node_set<order::following, FirstPredecessor, Predecessors...>(first_predecessor, predecessors...);
- }
- template<typename... Predecessors>
- node_set<order::following, Predecessors...>
- follows(node_set<order::undefined, Predecessors...>& predecessors_set) {
- __TBB_STATIC_ASSERT((tbb::internal::conjunction<has_output_type<Predecessors>...>::value),
- "Not all nodes in the set has output_type typedef");
- __TBB_STATIC_ASSERT((tbb::internal::conjunction<is_sender<Predecessors>...>::value),
- "Not all nodes in the set are senders");
- return node_set<order::following, Predecessors...>(predecessors_set);
- }
- template<typename FirstSuccessor, typename... Successors>
- node_set<order::preceding, FirstSuccessor, Successors...>
- precedes(FirstSuccessor& first_successor, Successors&... successors) {
- __TBB_STATIC_ASSERT((tbb::internal::conjunction<has_input_type<FirstSuccessor>,
- has_input_type<Successors>...>::value),
- "Not all node's successors has input_type typedef");
- __TBB_STATIC_ASSERT((tbb::internal::conjunction<is_receiver<FirstSuccessor>, is_receiver<Successors>...>::value),
- "Not all node's successors are receivers");
- return node_set<order::preceding, FirstSuccessor, Successors...>(first_successor, successors...);
- }
- template<typename... Successors>
- node_set<order::preceding, Successors...>
- precedes(node_set<order::undefined, Successors...>& successors_set) {
- __TBB_STATIC_ASSERT((tbb::internal::conjunction<has_input_type<Successors>...>::value),
- "Not all nodes in the set has input_type typedef");
- __TBB_STATIC_ASSERT((tbb::internal::conjunction<is_receiver<Successors>...>::value),
- "Not all nodes in the set are receivers");
- return node_set<order::preceding, Successors...>(successors_set);
- }
- template <typename Node, typename... Nodes>
- node_set<order::undefined, Node, Nodes...>
- make_node_set(Node& first_node, Nodes&... nodes) {
- return node_set<order::undefined, Node, Nodes...>(first_node, nodes...);
- }
- template<size_t I>
- class successor_selector {
- template <typename NodeType>
- static auto get_impl(NodeType& node, std::true_type) -> decltype(input_port<I>(node)) {
- return input_port<I>(node);
- }
- template <typename NodeType>
- static NodeType& get_impl(NodeType& node, std::false_type) { return node; }
- public:
- template <typename NodeType>
- #if __TBB_MSVC_DISABLE_TRAILING_DECLTYPE
- static auto& get(NodeType& node)
- #else
- static auto get(NodeType& node) -> decltype(get_impl(node, has_input_ports_type<NodeType>()))
- #endif
- {
- return get_impl(node, has_input_ports_type<NodeType>());
- }
- };
- template<size_t I>
- class predecessor_selector {
- template <typename NodeType>
- static auto internal_get(NodeType& node, std::true_type) -> decltype(output_port<I>(node)) {
- return output_port<I>(node);
- }
- template <typename NodeType>
- static NodeType& internal_get(NodeType& node, std::false_type) { return node;}
- template <typename NodeType>
- #if __TBB_MSVC_DISABLE_TRAILING_DECLTYPE
- static auto& get_impl(NodeType& node, std::false_type)
- #else
- static auto get_impl(NodeType& node, std::false_type) -> decltype(internal_get(node, has_output_ports_type<NodeType>()))
- #endif
- {
- return internal_get(node, has_output_ports_type<NodeType>());
- }
- template <typename AsyncNode>
- static AsyncNode& get_impl(AsyncNode& node, std::true_type) { return node; }
- public:
- template <typename NodeType>
- #if __TBB_MSVC_DISABLE_TRAILING_DECLTYPE
- static auto& get(NodeType& node)
- #else
- static auto get(NodeType& node) -> decltype(get_impl(node, is_async_node<NodeType>()))
- #endif
- {
- return get_impl(node, is_async_node<NodeType>());
- }
- };
- template<size_t I>
- class make_edges_helper {
- public:
- template<typename PredecessorsTuple, typename NodeType>
- static void connect_predecessors(PredecessorsTuple& predecessors, NodeType& node) {
- make_edge(std::get<I>(predecessors), successor_selector<I>::get(node));
- make_edges_helper<I - 1>::connect_predecessors(predecessors, node);
- }
- template<typename SuccessorsTuple, typename NodeType>
- static void connect_successors(NodeType& node, SuccessorsTuple& successors) {
- make_edge(predecessor_selector<I>::get(node), std::get<I>(successors));
- make_edges_helper<I - 1>::connect_successors(node, successors);
- }
- };
- template<>
- struct make_edges_helper<0> {
- template<typename PredecessorsTuple, typename NodeType>
- static void connect_predecessors(PredecessorsTuple& predecessors, NodeType& node) {
- make_edge(std::get<0>(predecessors), successor_selector<0>::get(node));
- }
- template<typename SuccessorsTuple, typename NodeType>
- static void connect_successors(NodeType& node, SuccessorsTuple& successors) {
- make_edge(predecessor_selector<0>::get(node), std::get<0>(successors));
- }
- };
- // TODO: consider adding an overload for making edges between node sets
- template<typename NodeType, typename OrderFlagType, typename... Args>
- void make_edges(const node_set<OrderFlagType, Args...>& s, NodeType& node) {
- const std::size_t SetSize = tbb::flow::tuple_size<decltype(s.nodes)>::value;
- make_edges_helper<SetSize - 1>::connect_predecessors(s.nodes, node);
- }
- template <typename NodeType, typename OrderFlagType, typename... Args>
- void make_edges(NodeType& node, const node_set<OrderFlagType, Args...>& s) {
- const std::size_t SetSize = tbb::flow::tuple_size<decltype(s.nodes)>::value;
- make_edges_helper<SetSize - 1>::connect_successors(node, s.nodes);
- }
- template <typename NodeType, typename... Nodes>
- void make_edges_in_order(const node_set<order::following, Nodes...>& ns, NodeType& node) {
- make_edges(ns, node);
- }
- template <typename NodeType, typename... Nodes>
- void make_edges_in_order(const node_set<order::preceding, Nodes...>& ns, NodeType& node) {
- make_edges(node, ns);
- }
- #endif // __TBB_CPP11_PRESENT
- } // namespace internal
- #endif // __TBB_flow_graph_node_set_impl_H
|