1 /*
2 Copyright (c) 2005-2020 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 #if __TBB_CPF_BUILD
18 #define TBB_DEPRECATED_FLOW_NODE_EXTRACTION 1
19 #endif
20
21 #include "harness.h"
22 #include "harness_graph.h"
23
24 #include "tbb/flow_graph.h"
25 #include "tbb/task_scheduler_init.h"
26 #include "test_follows_and_precedes_api.h"
27
28 #define N 300
29 #define T 4
30 #define M 4
31
32 template< typename R >
simple_read_write_tests()33 void simple_read_write_tests() {
34 tbb::flow::graph g;
35 tbb::flow::write_once_node<R> n(g);
36
37 for ( int t = 0; t < T; ++t ) {
38 R v0(0);
39 std::vector< harness_counting_receiver<R> > r(M, harness_counting_receiver<R>(g));
40
41 ASSERT( n.is_valid() == false, NULL );
42 ASSERT( n.try_get( v0 ) == false, NULL );
43
44 if ( t % 2 ) {
45 ASSERT( n.try_put( static_cast<R>(N+1) ), NULL );
46 ASSERT( n.is_valid() == true, NULL );
47 ASSERT( n.try_get( v0 ) == true, NULL );
48 ASSERT( v0 == R(N+1), NULL );
49 }
50
51 for (int i = 0; i < M; ++i) {
52 tbb::flow::make_edge( n, r[i] );
53 }
54
55 if ( t%2 ) {
56 for (int i = 0; i < M; ++i) {
57 size_t c = r[i].my_count;
58 ASSERT( int(c) == 1, NULL );
59 }
60 }
61
62 for (int i = 1; i <= N; ++i ) {
63 R v1(static_cast<R>(i));
64
65 bool result = n.try_put( v1 );
66 if ( !(t%2) && i == 1 )
67 ASSERT( result == true, NULL );
68 else
69 ASSERT( result == false, NULL );
70
71 ASSERT( n.is_valid() == true, NULL );
72
73 for (int j = 0; j < N; ++j ) {
74 R v2(0);
75 ASSERT( n.try_get( v2 ), NULL );
76 if ( t%2 )
77 ASSERT( R(N+1) == v2, NULL );
78 else
79 ASSERT( R(1) == v2, NULL );
80 }
81 }
82 for (int i = 0; i < M; ++i) {
83 size_t c = r[i].my_count;
84 ASSERT( int(c) == 1, NULL );
85 }
86 for (int i = 0; i < M; ++i) {
87 tbb::flow::remove_edge( n, r[i] );
88 }
89 ASSERT( n.try_put( R(0) ) == false, NULL );
90 for (int i = 0; i < M; ++i) {
91 size_t c = r[i].my_count;
92 ASSERT( int(c) == 1, NULL );
93 }
94 n.clear();
95 ASSERT( n.is_valid() == false, NULL );
96 ASSERT( n.try_get( v0 ) == false, NULL );
97 }
98 }
99
100 template< typename R >
101 class native_body : NoAssign {
102 tbb::flow::write_once_node<R> &my_node;
103
104 public:
105
native_body(tbb::flow::write_once_node<R> & n)106 native_body( tbb::flow::write_once_node<R> &n ) : my_node(n) {}
107
operator ()(int i) const108 void operator()( int i ) const {
109 R v1(static_cast<R>(i));
110 ASSERT( my_node.try_put( v1 ) == false, NULL );
111 ASSERT( my_node.is_valid() == true, NULL );
112 ASSERT( my_node.try_get( v1 ) == true, NULL );
113 ASSERT( v1 == R(-1), NULL );
114 }
115 };
116
117 template< typename R >
parallel_read_write_tests()118 void parallel_read_write_tests() {
119 tbb::flow::graph g;
120 tbb::flow::write_once_node<R> n(g);
121 //Create a vector of identical nodes
122 std::vector< tbb::flow::write_once_node<R> > wo_vec(2, n);
123
124 for (size_t node_idx=0; node_idx<wo_vec.size(); ++node_idx) {
125 for ( int t = 0; t < T; ++t ) {
126 std::vector< harness_counting_receiver<R> > r(M, harness_counting_receiver<R>(g));
127
128 for (int i = 0; i < M; ++i) {
129 tbb::flow::make_edge( wo_vec[node_idx], r[i] );
130 }
131 R v0;
132 ASSERT( wo_vec[node_idx].is_valid() == false, NULL );
133 ASSERT( wo_vec[node_idx].try_get( v0 ) == false, NULL );
134
135 ASSERT( wo_vec[node_idx].try_put( R(-1) ), NULL );
136
137 NativeParallelFor( N, native_body<R>( wo_vec[node_idx] ) );
138
139 for (int i = 0; i < M; ++i) {
140 size_t c = r[i].my_count;
141 ASSERT( int(c) == 1, NULL );
142 }
143 for (int i = 0; i < M; ++i) {
144 tbb::flow::remove_edge( wo_vec[node_idx], r[i] );
145 }
146 ASSERT( wo_vec[node_idx].try_put( R(0) ) == false, NULL );
147 for (int i = 0; i < M; ++i) {
148 size_t c = r[i].my_count;
149 ASSERT( int(c) == 1, NULL );
150 }
151 wo_vec[node_idx].clear();
152 ASSERT( wo_vec[node_idx].is_valid() == false, NULL );
153 ASSERT( wo_vec[node_idx].try_get( v0 ) == false, NULL );
154 }
155 }
156 }
157
158 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
159 #include <array>
160 #include <vector>
test_follows_and_precedes_api()161 void test_follows_and_precedes_api() {
162 using msg_t = tbb::flow::continue_msg;
163
164 std::array<msg_t, 3> messages_for_follows= {msg_t(), msg_t(), msg_t()};
165 std::vector<msg_t> messages_for_precedes = {msg_t()};
166
167 follows_and_precedes_testing::test_follows<msg_t, tbb::flow::write_once_node<msg_t>>(messages_for_follows);
168 follows_and_precedes_testing::test_precedes<msg_t, tbb::flow::write_once_node<msg_t>>(messages_for_precedes);
169 }
170 #endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
171
172 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
test_deduction_guides()173 void test_deduction_guides() {
174 using namespace tbb::flow;
175
176 graph g;
177 broadcast_node<int> b1(g);
178 write_once_node<int> wo0(g);
179
180 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
181 write_once_node wo1(follows(b1));
182 static_assert(std::is_same_v<decltype(wo1), write_once_node<int>>);
183
184 write_once_node wo2(precedes(b1));
185 static_assert(std::is_same_v<decltype(wo2), write_once_node<int>>);
186 #endif
187
188 write_once_node wo3(wo0);
189 static_assert(std::is_same_v<decltype(wo3), write_once_node<int>>);
190 }
191 #endif
192
TestMain()193 int TestMain() {
194 simple_read_write_tests<int>();
195 simple_read_write_tests<float>();
196 for( int p=MinThread; p<=MaxThread; ++p ) {
197 tbb::task_scheduler_init init(p);
198 parallel_read_write_tests<int>();
199 parallel_read_write_tests<float>();
200 test_reserving_nodes<tbb::flow::write_once_node, size_t>();
201 }
202 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
203 test_extract_on_node<tbb::flow::write_once_node, int>();
204 #endif
205 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
206 test_follows_and_precedes_api();
207 #endif
208 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
209 test_deduction_guides();
210 #endif
211 return Harness::Done;
212 }
213