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