1 | /* |
2 | Copyright (c) 2005-2019 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_graph.h" |
22 | |
23 | #include "tbb/flow_graph.h" |
24 | #include "tbb/task_scheduler_init.h" |
25 | |
26 | #define N 300 |
27 | #define T 4 |
28 | #define M 4 |
29 | |
30 | template< typename R > |
31 | void simple_read_write_tests() { |
32 | tbb::flow::graph g; |
33 | tbb::flow::write_once_node<R> n(g); |
34 | |
35 | for ( int t = 0; t < T; ++t ) { |
36 | R v0(0); |
37 | std::vector< harness_counting_receiver<R> > r(M, harness_counting_receiver<R>(g)); |
38 | |
39 | ASSERT( n.is_valid() == false, NULL ); |
40 | ASSERT( n.try_get( v0 ) == false, NULL ); |
41 | |
42 | if ( t % 2 ) { |
43 | ASSERT( n.try_put( static_cast<R>(N+1) ), NULL ); |
44 | ASSERT( n.is_valid() == true, NULL ); |
45 | ASSERT( n.try_get( v0 ) == true, NULL ); |
46 | ASSERT( v0 == R(N+1), NULL ); |
47 | } |
48 | |
49 | for (int i = 0; i < M; ++i) { |
50 | tbb::flow::make_edge( n, r[i] ); |
51 | } |
52 | |
53 | if ( t%2 ) { |
54 | for (int i = 0; i < M; ++i) { |
55 | size_t c = r[i].my_count; |
56 | ASSERT( int(c) == 1, NULL ); |
57 | } |
58 | } |
59 | |
60 | for (int i = 1; i <= N; ++i ) { |
61 | R v1(static_cast<R>(i)); |
62 | |
63 | bool result = n.try_put( v1 ); |
64 | if ( !(t%2) && i == 1 ) |
65 | ASSERT( result == true, NULL ); |
66 | else |
67 | ASSERT( result == false, NULL ); |
68 | |
69 | ASSERT( n.is_valid() == true, NULL ); |
70 | |
71 | for (int j = 0; j < N; ++j ) { |
72 | R v2(0); |
73 | ASSERT( n.try_get( v2 ), NULL ); |
74 | if ( t%2 ) |
75 | ASSERT( R(N+1) == v2, NULL ); |
76 | else |
77 | ASSERT( R(1) == v2, NULL ); |
78 | } |
79 | } |
80 | for (int i = 0; i < M; ++i) { |
81 | size_t c = r[i].my_count; |
82 | ASSERT( int(c) == 1, NULL ); |
83 | } |
84 | for (int i = 0; i < M; ++i) { |
85 | tbb::flow::remove_edge( n, r[i] ); |
86 | } |
87 | ASSERT( n.try_put( R(0) ) == false, NULL ); |
88 | for (int i = 0; i < M; ++i) { |
89 | size_t c = r[i].my_count; |
90 | ASSERT( int(c) == 1, NULL ); |
91 | } |
92 | n.clear(); |
93 | ASSERT( n.is_valid() == false, NULL ); |
94 | ASSERT( n.try_get( v0 ) == false, NULL ); |
95 | } |
96 | } |
97 | |
98 | template< typename R > |
99 | class native_body : NoAssign { |
100 | tbb::flow::write_once_node<R> &my_node; |
101 | |
102 | public: |
103 | |
104 | native_body( tbb::flow::write_once_node<R> &n ) : my_node(n) {} |
105 | |
106 | void operator()( int i ) const { |
107 | R v1(static_cast<R>(i)); |
108 | ASSERT( my_node.try_put( v1 ) == false, NULL ); |
109 | ASSERT( my_node.is_valid() == true, NULL ); |
110 | ASSERT( my_node.try_get( v1 ) == true, NULL ); |
111 | ASSERT( v1 == R(-1), NULL ); |
112 | } |
113 | }; |
114 | |
115 | template< typename R > |
116 | void parallel_read_write_tests() { |
117 | tbb::flow::graph g; |
118 | tbb::flow::write_once_node<R> n(g); |
119 | //Create a vector of identical nodes |
120 | std::vector< tbb::flow::write_once_node<R> > wo_vec(2, n); |
121 | |
122 | for (size_t node_idx=0; node_idx<wo_vec.size(); ++node_idx) { |
123 | for ( int t = 0; t < T; ++t ) { |
124 | std::vector< harness_counting_receiver<R> > r(M, harness_counting_receiver<R>(g)); |
125 | |
126 | for (int i = 0; i < M; ++i) { |
127 | tbb::flow::make_edge( wo_vec[node_idx], r[i] ); |
128 | } |
129 | R v0; |
130 | ASSERT( wo_vec[node_idx].is_valid() == false, NULL ); |
131 | ASSERT( wo_vec[node_idx].try_get( v0 ) == false, NULL ); |
132 | |
133 | ASSERT( wo_vec[node_idx].try_put( R(-1) ), NULL ); |
134 | |
135 | NativeParallelFor( N, native_body<R>( wo_vec[node_idx] ) ); |
136 | |
137 | for (int i = 0; i < M; ++i) { |
138 | size_t c = r[i].my_count; |
139 | ASSERT( int(c) == 1, NULL ); |
140 | } |
141 | for (int i = 0; i < M; ++i) { |
142 | tbb::flow::remove_edge( wo_vec[node_idx], r[i] ); |
143 | } |
144 | ASSERT( wo_vec[node_idx].try_put( R(0) ) == false, NULL ); |
145 | for (int i = 0; i < M; ++i) { |
146 | size_t c = r[i].my_count; |
147 | ASSERT( int(c) == 1, NULL ); |
148 | } |
149 | wo_vec[node_idx].clear(); |
150 | ASSERT( wo_vec[node_idx].is_valid() == false, NULL ); |
151 | ASSERT( wo_vec[node_idx].try_get( v0 ) == false, NULL ); |
152 | } |
153 | } |
154 | } |
155 | |
156 | int TestMain() { |
157 | simple_read_write_tests<int>(); |
158 | simple_read_write_tests<float>(); |
159 | for( int p=MinThread; p<=MaxThread; ++p ) { |
160 | tbb::task_scheduler_init init(p); |
161 | parallel_read_write_tests<int>(); |
162 | parallel_read_write_tests<float>(); |
163 | test_reserving_nodes<tbb::flow::write_once_node, size_t>(); |
164 | } |
165 | #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION |
166 | test_extract_on_node<tbb::flow::write_once_node, int>(); |
167 | #endif |
168 | return Harness::Done; |
169 | } |
170 | |
171 | |