1*e0cc5187SIlya Isaev /*
2*e0cc5187SIlya Isaev Copyright (c) 2022 Intel Corporation
3*e0cc5187SIlya Isaev
4*e0cc5187SIlya Isaev Licensed under the Apache License, Version 2.0 (the "License");
5*e0cc5187SIlya Isaev you may not use this file except in compliance with the License.
6*e0cc5187SIlya Isaev You may obtain a copy of the License at
7*e0cc5187SIlya Isaev
8*e0cc5187SIlya Isaev http://www.apache.org/licenses/LICENSE-2.0
9*e0cc5187SIlya Isaev
10*e0cc5187SIlya Isaev Unless required by applicable law or agreed to in writing, software
11*e0cc5187SIlya Isaev distributed under the License is distributed on an "AS IS" BASIS,
12*e0cc5187SIlya Isaev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e0cc5187SIlya Isaev See the License for the specific language governing permissions and
14*e0cc5187SIlya Isaev limitations under the License.
15*e0cc5187SIlya Isaev */
16*e0cc5187SIlya Isaev
17*e0cc5187SIlya Isaev #ifndef __TBB_test_common_test_join_node_multiple_predecessors_H_
18*e0cc5187SIlya Isaev #define __TBB_test_common_test_join_node_multiple_predecessors_H_
19*e0cc5187SIlya Isaev
20*e0cc5187SIlya Isaev #include "config.h"
21*e0cc5187SIlya Isaev #include "oneapi/tbb/flow_graph.h"
22*e0cc5187SIlya Isaev
23*e0cc5187SIlya Isaev namespace multiple_predecessors {
24*e0cc5187SIlya Isaev
25*e0cc5187SIlya Isaev using namespace tbb::flow;
26*e0cc5187SIlya Isaev
27*e0cc5187SIlya Isaev using join_node_t = join_node<std::tuple<continue_msg, continue_msg, continue_msg>, reserving>;
28*e0cc5187SIlya Isaev using queue_node_t = queue_node<std::tuple<continue_msg, continue_msg, continue_msg>>;
29*e0cc5187SIlya Isaev
twist_join_connections(buffer_node<continue_msg> & bn1,buffer_node<continue_msg> & bn2,buffer_node<continue_msg> & bn3,join_node_t & jn)30*e0cc5187SIlya Isaev void twist_join_connections(
31*e0cc5187SIlya Isaev buffer_node<continue_msg>& bn1, buffer_node<continue_msg>& bn2, buffer_node<continue_msg>& bn3,
32*e0cc5187SIlya Isaev join_node_t& jn)
33*e0cc5187SIlya Isaev {
34*e0cc5187SIlya Isaev // order, in which edges are created/destroyed, is important
35*e0cc5187SIlya Isaev make_edge(bn1, input_port<0>(jn));
36*e0cc5187SIlya Isaev make_edge(bn2, input_port<0>(jn));
37*e0cc5187SIlya Isaev make_edge(bn3, input_port<0>(jn));
38*e0cc5187SIlya Isaev
39*e0cc5187SIlya Isaev remove_edge(bn3, input_port<0>(jn));
40*e0cc5187SIlya Isaev make_edge (bn3, input_port<2>(jn));
41*e0cc5187SIlya Isaev
42*e0cc5187SIlya Isaev remove_edge(bn2, input_port<0>(jn));
43*e0cc5187SIlya Isaev make_edge (bn2, input_port<1>(jn));
44*e0cc5187SIlya Isaev }
45*e0cc5187SIlya Isaev
connect_join_via_make_edge(graph & g,buffer_node<continue_msg> & bn1,buffer_node<continue_msg> & bn2,buffer_node<continue_msg> & bn3,queue_node_t & qn)46*e0cc5187SIlya Isaev std::unique_ptr<join_node_t> connect_join_via_make_edge(
47*e0cc5187SIlya Isaev graph& g, buffer_node<continue_msg>& bn1, buffer_node<continue_msg>& bn2,
48*e0cc5187SIlya Isaev buffer_node<continue_msg>& bn3, queue_node_t& qn)
49*e0cc5187SIlya Isaev {
50*e0cc5187SIlya Isaev std::unique_ptr<join_node_t> jn( new join_node_t(g) );
51*e0cc5187SIlya Isaev twist_join_connections( bn1, bn2, bn3, *jn );
52*e0cc5187SIlya Isaev make_edge(*jn, qn);
53*e0cc5187SIlya Isaev return jn;
54*e0cc5187SIlya Isaev }
55*e0cc5187SIlya Isaev
56*e0cc5187SIlya Isaev #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
connect_join_via_follows(graph &,buffer_node<continue_msg> & bn1,buffer_node<continue_msg> & bn2,buffer_node<continue_msg> & bn3,queue_node_t & qn)57*e0cc5187SIlya Isaev std::unique_ptr<join_node_t> connect_join_via_follows(
58*e0cc5187SIlya Isaev graph&, buffer_node<continue_msg>& bn1, buffer_node<continue_msg>& bn2,
59*e0cc5187SIlya Isaev buffer_node<continue_msg>& bn3, queue_node_t& qn)
60*e0cc5187SIlya Isaev {
61*e0cc5187SIlya Isaev auto bn_set = make_node_set(bn1, bn2, bn3);
62*e0cc5187SIlya Isaev std::unique_ptr<join_node_t> jn( new join_node_t(follows(bn_set)) );
63*e0cc5187SIlya Isaev make_edge(*jn, qn);
64*e0cc5187SIlya Isaev return jn;
65*e0cc5187SIlya Isaev }
66*e0cc5187SIlya Isaev
connect_join_via_precedes(graph &,buffer_node<continue_msg> & bn1,buffer_node<continue_msg> & bn2,buffer_node<continue_msg> & bn3,queue_node_t & qn)67*e0cc5187SIlya Isaev std::unique_ptr<join_node_t> connect_join_via_precedes(
68*e0cc5187SIlya Isaev graph&, buffer_node<continue_msg>& bn1, buffer_node<continue_msg>& bn2,
69*e0cc5187SIlya Isaev buffer_node<continue_msg>& bn3, queue_node_t& qn)
70*e0cc5187SIlya Isaev {
71*e0cc5187SIlya Isaev auto qn_set = make_node_set(qn);
72*e0cc5187SIlya Isaev auto qn_copy_set = qn_set;
73*e0cc5187SIlya Isaev std::unique_ptr<join_node_t> jn( new join_node_t(precedes(qn_copy_set)) );
74*e0cc5187SIlya Isaev twist_join_connections( bn1, bn2, bn3, *jn );
75*e0cc5187SIlya Isaev return jn;
76*e0cc5187SIlya Isaev }
77*e0cc5187SIlya Isaev #endif // TBB_PREVIEW_FLOW_GRAPH_FEATURES
78*e0cc5187SIlya Isaev
run_and_check(graph & g,buffer_node<continue_msg> & bn1,buffer_node<continue_msg> & bn2,buffer_node<continue_msg> & bn3,queue_node_t & qn,bool expected)79*e0cc5187SIlya Isaev void run_and_check(
80*e0cc5187SIlya Isaev graph& g, buffer_node<continue_msg>& bn1, buffer_node<continue_msg>& bn2,
81*e0cc5187SIlya Isaev buffer_node<continue_msg>& bn3, queue_node_t& qn, bool expected)
82*e0cc5187SIlya Isaev {
83*e0cc5187SIlya Isaev std::tuple<continue_msg, continue_msg, continue_msg> msg;
84*e0cc5187SIlya Isaev
85*e0cc5187SIlya Isaev bn1.try_put(continue_msg());
86*e0cc5187SIlya Isaev bn2.try_put(continue_msg());
87*e0cc5187SIlya Isaev bn3.try_put(continue_msg());
88*e0cc5187SIlya Isaev g.wait_for_all();
89*e0cc5187SIlya Isaev
90*e0cc5187SIlya Isaev CHECK_MESSAGE(
91*e0cc5187SIlya Isaev (qn.try_get(msg) == expected),
92*e0cc5187SIlya Isaev "Unexpected message absence/existence at the end of the graph."
93*e0cc5187SIlya Isaev );
94*e0cc5187SIlya Isaev }
95*e0cc5187SIlya Isaev
96*e0cc5187SIlya Isaev template<typename ConnectJoinNodeFunc>
test(ConnectJoinNodeFunc && connect_join_node)97*e0cc5187SIlya Isaev void test(ConnectJoinNodeFunc&& connect_join_node) {
98*e0cc5187SIlya Isaev graph g;
99*e0cc5187SIlya Isaev buffer_node<continue_msg> bn1(g);
100*e0cc5187SIlya Isaev buffer_node<continue_msg> bn2(g);
101*e0cc5187SIlya Isaev buffer_node<continue_msg> bn3(g);
102*e0cc5187SIlya Isaev queue_node_t qn(g);
103*e0cc5187SIlya Isaev
104*e0cc5187SIlya Isaev auto jn = connect_join_node(g, bn1, bn2, bn3, qn);
105*e0cc5187SIlya Isaev
106*e0cc5187SIlya Isaev run_and_check(g, bn1, bn2, bn3, qn, /*expected=*/true);
107*e0cc5187SIlya Isaev
108*e0cc5187SIlya Isaev remove_edge(bn3, input_port<2>(*jn));
109*e0cc5187SIlya Isaev remove_edge(bn2, input_port<1>(*jn));
110*e0cc5187SIlya Isaev remove_edge(bn1, *jn); //Removes an edge between a sender and port 0 of a multi-input successor.
111*e0cc5187SIlya Isaev remove_edge(*jn, qn);
112*e0cc5187SIlya Isaev
113*e0cc5187SIlya Isaev run_and_check(g, bn1, bn2, bn3, qn, /*expected=*/false);
114*e0cc5187SIlya Isaev }
115*e0cc5187SIlya Isaev } // namespace multiple_predecessors
116*e0cc5187SIlya Isaev
117*e0cc5187SIlya Isaev #endif // __TBB_test_common_test_join_node_multiple_predecessors_H_
118