e5e9c8d5307774913a419b4a8d89a12109f4f1b1
[platform/upstream/tbb.git] / src / test / test_write_once_node.cpp
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