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
30template< typename R >
31void 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
98template< typename R >
99class native_body : NoAssign {
100 tbb::flow::write_once_node<R> &my_node;
101
102public:
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
115template< typename R >
116void 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
156int 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