151c0b2f7Stbbdev /*
2b15aabb3Stbbdev Copyright (c) 2020-2021 Intel Corporation
351c0b2f7Stbbdev
451c0b2f7Stbbdev Licensed under the Apache License, Version 2.0 (the "License");
551c0b2f7Stbbdev you may not use this file except in compliance with the License.
651c0b2f7Stbbdev You may obtain a copy of the License at
751c0b2f7Stbbdev
851c0b2f7Stbbdev http://www.apache.org/licenses/LICENSE-2.0
951c0b2f7Stbbdev
1051c0b2f7Stbbdev Unless required by applicable law or agreed to in writing, software
1151c0b2f7Stbbdev distributed under the License is distributed on an "AS IS" BASIS,
1251c0b2f7Stbbdev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1351c0b2f7Stbbdev See the License for the specific language governing permissions and
1451c0b2f7Stbbdev limitations under the License.
1551c0b2f7Stbbdev */
1651c0b2f7Stbbdev
17b15aabb3Stbbdev #if __INTEL_COMPILER && _MSC_VER
18b15aabb3Stbbdev #pragma warning(disable : 2586) // decorated name length exceeded, name was truncated
19b15aabb3Stbbdev #endif
20b15aabb3Stbbdev
21*de0109beSIlya Mishin #define CONFORMANCE_CONTINUE_NODE
2251c0b2f7Stbbdev
2351c0b2f7Stbbdev #include "conformance_flowgraph.h"
2451c0b2f7Stbbdev
2551c0b2f7Stbbdev //! \file conformance_continue_node.cpp
2651c0b2f7Stbbdev //! \brief Test for [flow_graph.continue_node] specification
2751c0b2f7Stbbdev
28*de0109beSIlya Mishin using output_msg = conformance::message</*default_ctor*/false, /*copy_ctor*/true, /*copy_assign*/true/*enable for queue_node successor*/>;
2951c0b2f7Stbbdev
3051c0b2f7Stbbdev #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
31*de0109beSIlya Mishin
32*de0109beSIlya Mishin template <typename ExpectedType, typename Body>
test_deduction_guides_common(Body body)33*de0109beSIlya Mishin void test_deduction_guides_common(Body body) {
34*de0109beSIlya Mishin using namespace tbb::flow;
35*de0109beSIlya Mishin graph g;
36*de0109beSIlya Mishin
37*de0109beSIlya Mishin continue_node c1(g, body);
38*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c1), continue_node<ExpectedType>>);
39*de0109beSIlya Mishin
40*de0109beSIlya Mishin continue_node c2(g, body, lightweight());
41*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c2), continue_node<ExpectedType, lightweight>>);
42*de0109beSIlya Mishin
43*de0109beSIlya Mishin continue_node c3(g, 5, body);
44*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c3), continue_node<ExpectedType>>);
45*de0109beSIlya Mishin
46*de0109beSIlya Mishin continue_node c4(g, 5, body, lightweight());
47*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c4), continue_node<ExpectedType, lightweight>>);
48*de0109beSIlya Mishin
49*de0109beSIlya Mishin continue_node c5(g, body, node_priority_t(5));
50*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c5), continue_node<ExpectedType>>);
51*de0109beSIlya Mishin
52*de0109beSIlya Mishin continue_node c6(g, body, lightweight(), node_priority_t(5));
53*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c6), continue_node<ExpectedType, lightweight>>);
54*de0109beSIlya Mishin
55*de0109beSIlya Mishin continue_node c7(g, 5, body, node_priority_t(5));
56*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c7), continue_node<ExpectedType>>);
57*de0109beSIlya Mishin
58*de0109beSIlya Mishin continue_node c8(g, 5, body, lightweight(), node_priority_t(5));
59*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c8), continue_node<ExpectedType, lightweight>>);
60*de0109beSIlya Mishin
61*de0109beSIlya Mishin #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
62*de0109beSIlya Mishin broadcast_node<continue_msg> b(g);
63*de0109beSIlya Mishin
64*de0109beSIlya Mishin continue_node c9(follows(b), body);
65*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c9), continue_node<ExpectedType>>);
66*de0109beSIlya Mishin
67*de0109beSIlya Mishin continue_node c10(follows(b), body, lightweight());
68*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c10), continue_node<ExpectedType, lightweight>>);
69*de0109beSIlya Mishin
70*de0109beSIlya Mishin continue_node c11(follows(b), 5, body);
71*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c11), continue_node<ExpectedType>>);
72*de0109beSIlya Mishin
73*de0109beSIlya Mishin continue_node c12(follows(b), 5, body, lightweight());
74*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c12), continue_node<ExpectedType, lightweight>>);
75*de0109beSIlya Mishin
76*de0109beSIlya Mishin continue_node c13(follows(b), body, node_priority_t(5));
77*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c13), continue_node<ExpectedType>>);
78*de0109beSIlya Mishin
79*de0109beSIlya Mishin continue_node c14(follows(b), body, lightweight(), node_priority_t(5));
80*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c14), continue_node<ExpectedType, lightweight>>);
81*de0109beSIlya Mishin
82*de0109beSIlya Mishin continue_node c15(follows(b), 5, body, node_priority_t(5));
83*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c15), continue_node<ExpectedType>>);
84*de0109beSIlya Mishin
85*de0109beSIlya Mishin continue_node c16(follows(b), 5, body, lightweight(), node_priority_t(5));
86*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c16), continue_node<ExpectedType, lightweight>>);
87*de0109beSIlya Mishin #endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
88*de0109beSIlya Mishin
89*de0109beSIlya Mishin continue_node c17(c1);
90*de0109beSIlya Mishin static_assert(std::is_same_v<decltype(c17), continue_node<ExpectedType>>);
91*de0109beSIlya Mishin }
92*de0109beSIlya Mishin
continue_body_f(const tbb::flow::continue_msg &)93*de0109beSIlya Mishin int continue_body_f(const tbb::flow::continue_msg&) { return 1; }
continue_void_body_f(const tbb::flow::continue_msg &)94*de0109beSIlya Mishin void continue_void_body_f(const tbb::flow::continue_msg&) {}
95*de0109beSIlya Mishin
test_deduction_guides()9651c0b2f7Stbbdev void test_deduction_guides() {
97*de0109beSIlya Mishin using tbb::flow::continue_msg;
98*de0109beSIlya Mishin test_deduction_guides_common<int>([](const continue_msg&)->int { return 1; } );
99*de0109beSIlya Mishin test_deduction_guides_common<continue_msg>([](const continue_msg&) {});
10051c0b2f7Stbbdev
101*de0109beSIlya Mishin test_deduction_guides_common<int>([](const continue_msg&) mutable ->int { return 1; });
102*de0109beSIlya Mishin test_deduction_guides_common<continue_msg>([](const continue_msg&) mutable {});
10351c0b2f7Stbbdev
104*de0109beSIlya Mishin test_deduction_guides_common<int>(continue_body_f);
105*de0109beSIlya Mishin test_deduction_guides_common<continue_msg>(continue_void_body_f);
10651c0b2f7Stbbdev }
10751c0b2f7Stbbdev
108*de0109beSIlya Mishin #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
10951c0b2f7Stbbdev
110*de0109beSIlya Mishin //! Test execution of node body
111*de0109beSIlya Mishin //! Test node can do try_put call
112*de0109beSIlya Mishin //! \brief \ref interface \ref requirement
113*de0109beSIlya Mishin TEST_CASE("continue body") {
114*de0109beSIlya Mishin conformance::test_body_exec<oneapi::tbb::flow::continue_node<output_msg>, oneapi::tbb::flow::continue_msg, output_msg>();
11551c0b2f7Stbbdev }
11651c0b2f7Stbbdev
117*de0109beSIlya Mishin //! Test continue_node is a graph_node, receiver<continue_msg>, and sender<Output>
118*de0109beSIlya Mishin //! \brief \ref interface
119*de0109beSIlya Mishin TEST_CASE("continue_node superclasses"){
120*de0109beSIlya Mishin conformance::test_inheritance<oneapi::tbb::flow::continue_node<int>, oneapi::tbb::flow::continue_msg, int>();
121*de0109beSIlya Mishin conformance::test_inheritance<oneapi::tbb::flow::continue_node<void*>, oneapi::tbb::flow::continue_msg, void*>();
122*de0109beSIlya Mishin conformance::test_inheritance<oneapi::tbb::flow::continue_node<output_msg>, oneapi::tbb::flow::continue_msg, output_msg>();
12351c0b2f7Stbbdev }
12451c0b2f7Stbbdev
12551c0b2f7Stbbdev //! Test body copying and copy_body logic
126*de0109beSIlya Mishin //! Test the body object passed to a node is copied
12751c0b2f7Stbbdev //! \brief \ref interface
12851c0b2f7Stbbdev TEST_CASE("continue_node and body copying"){
129*de0109beSIlya Mishin conformance::test_copy_body_function<oneapi::tbb::flow::continue_node<int>, conformance::copy_counting_object<int, oneapi::tbb::flow::continue_msg>>();
13051c0b2f7Stbbdev }
13151c0b2f7Stbbdev
13251c0b2f7Stbbdev //! Test deduction guides
13351c0b2f7Stbbdev //! \brief \ref interface \ref requirement
13451c0b2f7Stbbdev TEST_CASE("Deduction guides"){
13551c0b2f7Stbbdev #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
13651c0b2f7Stbbdev test_deduction_guides();
13751c0b2f7Stbbdev #endif
13851c0b2f7Stbbdev }
13951c0b2f7Stbbdev
140*de0109beSIlya Mishin //! Test node broadcast messages to successors
141*de0109beSIlya Mishin //! \brief \ref requirement
142*de0109beSIlya Mishin TEST_CASE("continue_node broadcast"){
143*de0109beSIlya Mishin conformance::counting_functor<int> fun(conformance::expected);
144*de0109beSIlya Mishin conformance::test_forwarding<oneapi::tbb::flow::continue_node<int>, oneapi::tbb::flow::continue_msg, int>(1, fun);
14551c0b2f7Stbbdev }
14651c0b2f7Stbbdev
147*de0109beSIlya Mishin //! Test node not buffered unsuccessful message, and try_get after rejection should not succeed.
148*de0109beSIlya Mishin //! \brief \ref requirement
149*de0109beSIlya Mishin TEST_CASE("continue_node buffering"){
150*de0109beSIlya Mishin conformance::dummy_functor<int> fun;
151*de0109beSIlya Mishin conformance::test_buffering<oneapi::tbb::flow::continue_node<int>, oneapi::tbb::flow::continue_msg>(fun);
152*de0109beSIlya Mishin }
153*de0109beSIlya Mishin
154*de0109beSIlya Mishin //! Test all node costructors
155*de0109beSIlya Mishin //! \brief \ref requirement
156*de0109beSIlya Mishin TEST_CASE("continue_node constructors"){
157*de0109beSIlya Mishin using namespace oneapi::tbb::flow;
158*de0109beSIlya Mishin graph g;
159*de0109beSIlya Mishin
160*de0109beSIlya Mishin conformance::counting_functor<int> fun;
161*de0109beSIlya Mishin
162*de0109beSIlya Mishin continue_node<int> proto1(g, fun);
163*de0109beSIlya Mishin continue_node<int> proto2(g, fun, oneapi::tbb::flow::node_priority_t(1));
164*de0109beSIlya Mishin continue_node<int> proto3(g, 2, fun);
165*de0109beSIlya Mishin continue_node<int> proto4(g, 2, fun, oneapi::tbb::flow::node_priority_t(1));
166*de0109beSIlya Mishin
167*de0109beSIlya Mishin continue_node<int, lightweight> lw_node1(g, fun, lightweight());
168*de0109beSIlya Mishin continue_node<int, lightweight> lw_node2(g, fun, lightweight(), oneapi::tbb::flow::node_priority_t(1));
169*de0109beSIlya Mishin continue_node<int, lightweight> lw_node3(g, 2, fun, lightweight());
170*de0109beSIlya Mishin continue_node<int, lightweight> lw_node4(g, 2, fun, lightweight(), oneapi::tbb::flow::node_priority_t(1));
171*de0109beSIlya Mishin }
172*de0109beSIlya Mishin
173*de0109beSIlya Mishin //! The node that is constructed has a reference to the same graph object as src,
174*de0109beSIlya Mishin //! has a copy of the initial body used by src, and only has a non-zero threshold if src is constructed with a non-zero threshold..
175*de0109beSIlya Mishin //! The predecessors and successors of src are not copied.
176*de0109beSIlya Mishin //! \brief \ref interface
177*de0109beSIlya Mishin TEST_CASE("continue_node copy constructor"){
178*de0109beSIlya Mishin using namespace oneapi::tbb::flow;
179*de0109beSIlya Mishin graph g;
180*de0109beSIlya Mishin
181*de0109beSIlya Mishin conformance::dummy_functor<oneapi::tbb::flow::continue_msg> fun1;
182*de0109beSIlya Mishin using counting_body = conformance::copy_counting_object<output_msg, oneapi::tbb::flow::continue_msg>;
183*de0109beSIlya Mishin counting_body fun2;
184*de0109beSIlya Mishin
185*de0109beSIlya Mishin continue_node<oneapi::tbb::flow::continue_msg> node0(g, fun1);
186*de0109beSIlya Mishin continue_node<output_msg> node1(g, 2, fun2);
187*de0109beSIlya Mishin conformance::test_push_receiver<output_msg> node2(g);
188*de0109beSIlya Mishin conformance::test_push_receiver<output_msg> node3(g);
189*de0109beSIlya Mishin
190*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(node0, node1);
191*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(node1, node2);
192*de0109beSIlya Mishin
193*de0109beSIlya Mishin continue_node<output_msg> node_copy(node1);
194*de0109beSIlya Mishin
195*de0109beSIlya Mishin counting_body b2 = copy_body<counting_body, continue_node<output_msg>>(node_copy);
196*de0109beSIlya Mishin
197*de0109beSIlya Mishin CHECK_MESSAGE((fun2.copy_count + 1 < b2.copy_count), "constructor should copy bodies");
198*de0109beSIlya Mishin
199*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(node_copy, node3);
200*de0109beSIlya Mishin
201*de0109beSIlya Mishin node_copy.try_put(oneapi::tbb::flow::continue_msg());
202*de0109beSIlya Mishin g.wait_for_all();
203*de0109beSIlya Mishin
204*de0109beSIlya Mishin CHECK_MESSAGE((conformance::get_values(node2).size() == 0 && conformance::get_values(node3).size() == 0), "Copied node doesn`t copy successor, but copy number of predecessors");
205*de0109beSIlya Mishin
206*de0109beSIlya Mishin node_copy.try_put(oneapi::tbb::flow::continue_msg());
207*de0109beSIlya Mishin g.wait_for_all();
208*de0109beSIlya Mishin
209*de0109beSIlya Mishin CHECK_MESSAGE((conformance::get_values(node2).size() == 0 && conformance::get_values(node3).size() == 1), "Copied node doesn`t copy successor, but copy number of predecessors");
210*de0109beSIlya Mishin
211*de0109beSIlya Mishin node1.try_put(oneapi::tbb::flow::continue_msg());
212*de0109beSIlya Mishin node1.try_put(oneapi::tbb::flow::continue_msg());
213*de0109beSIlya Mishin node0.try_put(oneapi::tbb::flow::continue_msg());
214*de0109beSIlya Mishin g.wait_for_all();
215*de0109beSIlya Mishin
216*de0109beSIlya Mishin CHECK_MESSAGE((conformance::get_values(node2).size() == 1 && conformance::get_values(node3).size() == 0), "Copied node doesn`t copy predecessor, but copy number of predecessors");
217*de0109beSIlya Mishin }
218*de0109beSIlya Mishin
219*de0109beSIlya Mishin //! Test continue_node wait for their predecessors to complete before executing, but no explicit data is passed across the incoming edges.
220*de0109beSIlya Mishin //! \brief \ref requirement
221*de0109beSIlya Mishin TEST_CASE("continue_node number_of_predecessors") {
222*de0109beSIlya Mishin oneapi::tbb::flow::graph g;
223*de0109beSIlya Mishin
224*de0109beSIlya Mishin conformance::counting_functor<int> fun;
225*de0109beSIlya Mishin
226*de0109beSIlya Mishin oneapi::tbb::flow::continue_node<oneapi::tbb::flow::continue_msg> node1(g, fun);
227*de0109beSIlya Mishin oneapi::tbb::flow::continue_node<oneapi::tbb::flow::continue_msg> node2(g, 1, fun);
228*de0109beSIlya Mishin oneapi::tbb::flow::continue_node<oneapi::tbb::flow::continue_msg> node3(g, 1, fun);
229*de0109beSIlya Mishin oneapi::tbb::flow::continue_node<int> node4(g, fun);
230*de0109beSIlya Mishin
231*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(node1, node2);
232*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(node2, node4);
233*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(node1, node3);
234*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(node1, node3);
235*de0109beSIlya Mishin oneapi::tbb::flow::remove_edge(node1, node3);
236*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(node3, node4);
237*de0109beSIlya Mishin node3.try_put(oneapi::tbb::flow::continue_msg());
238*de0109beSIlya Mishin node2.try_put(oneapi::tbb::flow::continue_msg());
239*de0109beSIlya Mishin node1.try_put(oneapi::tbb::flow::continue_msg());
240*de0109beSIlya Mishin
241*de0109beSIlya Mishin g.wait_for_all();
242*de0109beSIlya Mishin CHECK_MESSAGE((fun.execute_count == 4), "Node wait for their predecessors to complete before executing");
243*de0109beSIlya Mishin }
244*de0109beSIlya Mishin
245*de0109beSIlya Mishin //! Test nodes for execution with priority in single-threaded configuration
246*de0109beSIlya Mishin //! \brief \ref requirement
247*de0109beSIlya Mishin TEST_CASE("continue_node priority support"){
248*de0109beSIlya Mishin conformance::test_priority<oneapi::tbb::flow::continue_node<oneapi::tbb::flow::continue_msg, int>, oneapi::tbb::flow::continue_msg>();
249*de0109beSIlya Mishin }
250*de0109beSIlya Mishin
251*de0109beSIlya Mishin //! Test node Output class meet the CopyConstructible requirements.
252*de0109beSIlya Mishin //! \brief \ref requirement
253*de0109beSIlya Mishin TEST_CASE("continue_node Output class") {
254*de0109beSIlya Mishin conformance::test_output_class<oneapi::tbb::flow::continue_node<conformance::copy_counting_object<int, oneapi::tbb::flow::continue_msg>>, conformance::copy_counting_object<int, oneapi::tbb::flow::continue_msg>>();
255*de0109beSIlya Mishin }
256*de0109beSIlya Mishin
257*de0109beSIlya Mishin //! Test body `try_put' statement not wait for the execution of the body to complete
258*de0109beSIlya Mishin //! \brief \ref requirement
259*de0109beSIlya Mishin TEST_CASE("continue_node `try_put' statement not wait for the execution of the body to complete") {
260*de0109beSIlya Mishin conformance::wait_flag_body body;
261*de0109beSIlya Mishin oneapi::tbb::flow::graph g;
262*de0109beSIlya Mishin
263*de0109beSIlya Mishin oneapi::tbb::flow::continue_node<oneapi::tbb::flow::continue_msg> node1(g, body);
264*de0109beSIlya Mishin node1.try_put(oneapi::tbb::flow::continue_msg());
265*de0109beSIlya Mishin conformance::wait_flag_body::flag.store(true);
266*de0109beSIlya Mishin g.wait_for_all();
26751c0b2f7Stbbdev }
268