Line data Source code
1 :
2 : /* Copyright (c) 2010-2012, Stefan Eilemann <eile@equalizergraphics.com>
3 : *
4 : * This library is free software; you can redistribute it and/or modify it under
5 : * the terms of the GNU Lesser General Public License version 2.1 as published
6 : * by the Free Software Foundation.
7 : *
8 : * This library is distributed in the hope that it will be useful, but WITHOUT
9 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 : * details.
12 : *
13 : * You should have received a copy of the GNU Lesser General Public License
14 : * along with this library; if not, write to the Free Software Foundation, Inc.,
15 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 : */
17 :
18 : #define TEST_RUNTIME 300 // seconds
19 : #include "test.h"
20 :
21 : #include <lunchbox/clock.h>
22 : #include <lunchbox/monitor.h>
23 : #include <lunchbox/thread.h>
24 : #include <iostream>
25 :
26 : using servus::uint128_t;
27 :
28 1 : lunchbox::Monitor< int64_t > monitor;
29 1 : lunchbox::Monitor< bool > boolMonitor;
30 :
31 : class Thread1 : public lunchbox::Thread
32 : {
33 : public:
34 1 : explicit Thread1( int64_t loops ) : _loops( loops ) {}
35 1 : virtual ~Thread1() {}
36 1 : virtual void run()
37 : {
38 1 : int64_t nOps = _loops;
39 1 : lunchbox::Clock clock;
40 200002 : while( nOps-- )
41 : {
42 200000 : monitor.waitEQ( nOps );
43 200000 : monitor = -nOps;
44 : }
45 :
46 1 : const float time = clock.getTimef();
47 1 : std::cout << 2*_loops / time << " ops/ms" << std::endl;
48 1 : }
49 : private:
50 : int64_t _loops;
51 : };
52 :
53 1 : void testSimpleMonitor()
54 : {
55 1 : TEST( !boolMonitor );
56 1 : boolMonitor = true;
57 1 : TEST( boolMonitor );
58 :
59 1 : const int64_t loops = 200000;
60 1 : int64_t nOps = loops;
61 1 : Thread1 waiter( nOps );
62 :
63 1 : TEST( waiter.start( ));
64 2 : lunchbox::Clock clock;
65 :
66 200002 : while( nOps-- )
67 : {
68 200000 : monitor = nOps;
69 200000 : monitor.waitEQ( -nOps );
70 : }
71 :
72 1 : const float time = clock.getTimef();
73 :
74 1 : TEST( waiter.join( ));
75 2 : std::cout << 2*loops / time << " ops/ms" << std::endl;
76 1 : }
77 :
78 : class Thread2 : public lunchbox::Thread
79 : {
80 : public:
81 2 : explicit Thread2( size_t loops )
82 : : innerLoops( 0 )
83 2 : , _outerLoops( loops )
84 2 : {}
85 :
86 2 : virtual ~Thread2() {}
87 2 : virtual void run()
88 : {
89 2 : lunchbox::Clock clock;
90 2 : size_t ops = 0;
91 6 : for( size_t k = 0; k != 2; ++k )
92 : {
93 4004 : for( size_t i = 0; i != _outerLoops; ++i )
94 : {
95 4000 : const int64_t loops = innerLoops.waitNE( 0 );
96 4000 : innerLoops = 0;
97 2006000 : for( int64_t j = 0; j != loops; ++j )
98 : {
99 2002000 : if (innerLoops > 0)
100 0 : abort();
101 2002000 : ++monitor;
102 : }
103 4000 : ops += loops * 2 + 2;
104 : }
105 : }
106 :
107 6 : for( size_t k = 0; k != 2; ++k )
108 : {
109 4004 : for( size_t i = 0; i != _outerLoops; ++i )
110 : {
111 4000 : const int64_t loops = innerLoops.waitNE( 0 );
112 4000 : innerLoops = 0;
113 2006000 : for( int64_t j = 0; j != loops; ++j )
114 : {
115 2002000 : if (innerLoops > 0)
116 0 : abort();
117 2002000 : --monitor;
118 : }
119 4000 : ops += loops * 2 + 2;
120 : }
121 : }
122 :
123 2 : const float time = clock.getTimef();
124 2 : std::cout << ops/time << " ops/ms" << std::endl;
125 2 : }
126 :
127 : lunchbox::Monitor< int64_t > innerLoops;
128 : private:
129 : size_t _outerLoops;
130 : };
131 :
132 1 : void testMonitorComparisons()
133 : {
134 1 : boolMonitor = true;
135 1 : const int64_t loops = 1000;
136 1 : Thread2 waiter( loops );
137 1 : TEST( waiter.start( ));
138 :
139 1001 : for( int64_t i = 0; i != loops; ++i )
140 : {
141 1000 : monitor = 0;
142 1000 : waiter.innerLoops = i + 1;
143 1000 : TEST( monitor.waitGE( i + 1 ) >= i + 1 );
144 1000 : TEST( monitor >= i + 1 );
145 : }
146 :
147 1001 : for( int64_t i = 0; i != loops; ++i )
148 : {
149 1000 : monitor = 0;
150 1000 : waiter.innerLoops = i + 1;
151 1000 : TEST( monitor.waitGT( i ) > i );
152 1000 : TEST( monitor > i );
153 : }
154 :
155 1001 : for( int64_t i = 0; i != loops; ++i )
156 : {
157 1000 : monitor = i + 1;
158 1000 : waiter.innerLoops = i + 1;
159 1000 : TEST( monitor.waitLE( 0 ) <= 0 );
160 1000 : TEST( monitor <= 0 );
161 : }
162 :
163 1001 : for( int64_t i = 0; i != loops; ++i )
164 : {
165 1000 : monitor = i + 1;
166 1000 : waiter.innerLoops = i + 1;
167 1000 : TEST( monitor.waitLT( 1 ) < 1 );
168 1000 : TEST( monitor < 1 );
169 : }
170 :
171 1 : TEST( waiter.join( ));
172 1 : }
173 :
174 1 : void testTimedMonitorComparisons()
175 : {
176 1 : boolMonitor = true;
177 1 : const size_t loops = 1000;
178 1 : Thread2 waiter( loops );
179 1 : TEST( waiter.start( ));
180 1 : const uint32_t timeout = 1;
181 :
182 1001 : for( size_t i = 0; i != loops; ++i )
183 : {
184 1000 : monitor = 0;
185 1000 : waiter.innerLoops = i + 1;
186 1000 : while( !monitor.timedWaitGE( i + 1, timeout ))
187 : ;
188 1000 : TEST( monitor >= i + 1 );
189 : }
190 1001 : for( size_t i = 0; i != loops; ++i )
191 : {
192 1000 : monitor = 0;
193 1000 : waiter.innerLoops = i + 1;
194 1000 : while( !monitor.timedWaitGT( i, timeout ))
195 : ;
196 1000 : TEST( monitor > i );
197 : }
198 1001 : for( size_t i = 0; i != loops; ++i )
199 : {
200 1000 : monitor = i + 1;
201 1000 : waiter.innerLoops = i + 1;
202 1000 : while( !monitor.timedWaitLE( 0, timeout ))
203 : ;
204 1000 : TEST( monitor <= 0 );
205 : }
206 1001 : for( size_t i = 0; i != loops; ++i )
207 : {
208 1000 : monitor = i + 1;
209 1000 : waiter.innerLoops = i + 1;
210 1000 : while( !monitor.timedWaitLT( 1, timeout ))
211 : ;
212 1000 : TEST( monitor < 1 );
213 : }
214 :
215 1 : TEST( waiter.join( ));
216 1 : }
217 :
218 1 : int main( int, char** )
219 : {
220 1 : testSimpleMonitor();
221 1 : testMonitorComparisons();
222 1 : testTimedMonitorComparisons();
223 1 : return EXIT_SUCCESS;
224 3 : }
|