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
30template< typename R >
31void 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
88template< typename R >
89class native_body : NoAssign {
90 tbb::flow::overwrite_node<R> &my_node;
91
92public:
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
103template< typename R >
104void 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
142int 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