/[resiprocate]/main/rutil/test/testFifo.cxx
ViewVC logotype

Contents of /main/rutil/test/testFifo.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5930 - (show annotations) (download)
Thu Feb 16 22:39:14 2006 UTC (13 years, 9 months ago) by dworley
File size: 12561 byte(s)
Start cleaning up svn:eol-style and EOLs in files.
Note that text and program files that can be used on both Un*x and Windows
should have svn:eol-style=native so they check out correctly on both
platforms.

1 #include <iostream>
2 #include "rutil/Log.hxx"
3 #include "rutil/Fifo.hxx"
4 #include "rutil/FiniteFifo.hxx"
5 #include "rutil/TimeLimitFifo.hxx"
6 #include "rutil/Data.hxx"
7 #include "rutil/ThreadIf.hxx"
8 #include "rutil/Timer.hxx"
9 #ifndef WIN32
10 #include <unistd.h>
11 #endif
12
13 //#define VERBOSE
14
15 using namespace resip;
16 using namespace std;
17
18 void sleepMS(unsigned int ms)
19 {
20 #ifdef WIN32
21 Sleep(ms);
22 #else
23 usleep(ms*1000);
24 #endif
25 }
26
27 class Foo
28 {
29 public:
30 Foo(const Data& val)
31 : mVal(val)
32 {}
33
34 Data mVal;
35 };
36
37 class Consumer: public ThreadIf
38 {
39 public:
40 Consumer(TimeLimitFifo<Foo>&);
41 virtual ~Consumer()
42 {
43 #ifdef VERBOSE
44 cerr << "Consumer thread finishing..." << endl;
45 #endif
46 shutdown();
47 join();
48 #ifdef VERBOSE
49 cerr << "Consumer thread finished" << endl;
50 #endif
51 };
52
53 void thread();
54
55 private:
56 TimeLimitFifo<Foo>& mFifo;
57 };
58
59 class Producer: public ThreadIf
60 {
61 public:
62 Producer(TimeLimitFifo<Foo>&);
63 virtual ~Producer()
64 {
65 #ifdef VERBOSE
66 cerr << "Producer thread finishing" << endl;
67 #endif
68 shutdown();
69 join();
70 #ifdef VERBOSE
71 cerr << "Producer thread finished" << endl;
72 #endif
73 }
74
75 void thread();
76
77 private:
78 TimeLimitFifo<Foo>& mFifo;
79 };
80
81 Consumer::Consumer(TimeLimitFifo<Foo>& f) :
82 mFifo(f)
83 {}
84
85 void Consumer::thread()
86 {
87 static unsigned wakeups[6] = { 10, 20, 30, 0, 10, 30 };
88 unsigned int w = 0;
89
90 #ifdef VERBOSE
91 cerr << "Consumer running..." << endl;
92 #endif
93
94 while (!mShutdown)
95 {
96 if (mFifo.messageAvailable())
97 {
98 mFifo.getNext(100);
99 }
100 else
101 {
102 unsigned wakeup = wakeups[w];
103 w = (w + 1) % 6;
104 #ifdef VERBOSE
105 cerr << "Consumer sleeping for " << wakeup << " ms with mSize " << mFifo.size() << endl;
106 #endif
107 if (wakeup > 0)
108 {
109 sleepMS(wakeup);
110 }
111 }
112 }
113 }
114
115 Producer::Producer(TimeLimitFifo<Foo>& f) :
116 mFifo(f)
117 {}
118
119 void Producer::thread()
120 {
121 static unsigned wakeups[6] = { 0, 10, 0, 20, 30, 10 };
122 unsigned int w = 0;
123
124 #ifdef VERBOSE
125 cerr << "Producer running..." << endl;
126 #endif
127
128 for (unsigned long n = 0; n < 0x1ffff; n++)
129 {
130 if (mFifo.wouldAccept(TimeLimitFifo<Foo>::EnforceTimeDepth))
131 {
132 mFifo.add(new Foo(Data(n)), TimeLimitFifo<Foo>::EnforceTimeDepth);
133 }
134 else
135 {
136 unsigned wakeup = wakeups[w];
137 w = (w + 1) % 6;
138 #ifdef VERBOSE
139 cerr << "Producer sleeping for " << wakeup << " ms at " << n << " with mSize " << mFifo.size() << endl;
140 #endif
141 if (wakeup > 0)
142 {
143 sleepMS(wakeup);
144 }
145 }
146 }
147 }
148
149 bool
150 isNear(int value, int reference, int epsilon=250)
151 {
152 int diff = ::abs(value-reference);
153 return (diff < epsilon);
154 }
155
156 int
157 main()
158 {
159 Log::initialize(Log::Cout, Log::Debug, Data::Empty);
160
161 {
162 cerr << "!! test getNext(ms) empty fifo timing" << endl;
163 Fifo<Foo> fifo;
164 UInt64 begin(Timer::getTimeMs());
165 fifo.getNext(2000);
166 UInt64 end(Timer::getTimeMs());
167 cerr << begin << " " << end << " " << end-begin << endl;
168
169 int offMark = 2000 - (end - begin);
170
171 assert(abs(offMark) < 200);
172 }
173
174 Fifo<Foo> f;
175 FiniteFifo<Foo> ff(5);
176
177 {
178 cerr << "!! test basic" << endl;
179
180 bool c;
181 TimeLimitFifo<Foo> tlf(5, 10); // 5 seconds or 10 count limit
182
183 assert(tlf.empty());
184 assert(tlf.size() == 0);
185 assert(tlf.timeDepth() == 0);
186
187 c = tlf.add(new Foo("first"), TimeLimitFifo<Foo>::EnforceTimeDepth);
188 assert(c);
189
190 #ifdef VERBOSE
191 cerr << __LINE__ << endl;
192 #endif
193
194 assert(!tlf.empty());
195 assert(tlf.size() == 1);
196 #ifdef VERBOSE
197 cerr << tlf.timeDepth() << endl;
198 #endif
199 assert(tlf.timeDepth() == 0);
200
201 #ifdef VERBOSE
202 cerr << __LINE__ << endl;
203 #endif
204
205 sleepMS(2000);
206
207 assert(!tlf.empty());
208 assert(tlf.size() == 1);
209 assert(tlf.timeDepth() > 1);
210
211 delete tlf.getNext();
212
213 assert(tlf.empty());
214 assert(tlf.size() == 0);
215 assert(tlf.timeDepth() == 0);
216
217 #ifdef VERBOSE
218 cerr << __LINE__ << endl;
219 #endif
220
221 c = tlf.add(new Foo("first"), TimeLimitFifo<Foo>::EnforceTimeDepth);
222 assert(c);
223 sleepMS(3000);
224 c = tlf.add(new Foo("second"), TimeLimitFifo<Foo>::EnforceTimeDepth);
225 assert(c);
226 sleepMS(3000);
227 c = tlf.add(new Foo("nope"), TimeLimitFifo<Foo>::EnforceTimeDepth);
228 assert(!c);
229 c = tlf.add(new Foo("yep"), TimeLimitFifo<Foo>::IgnoreTimeDepth);
230 assert(c);
231 c = tlf.add(new Foo("internal"), TimeLimitFifo<Foo>::InternalElement);
232 assert(c);
233
234 cerr << __LINE__ << endl;
235
236 Foo* fp = tlf.getNext();
237 assert(fp->mVal == "first");
238 delete fp;
239 c = tlf.add(new Foo("third"), TimeLimitFifo<Foo>::EnforceTimeDepth);
240 assert(c);
241 }
242
243 {
244 cerr << "!! Test time depth" << endl;
245
246 TimeLimitFifo<Foo> tlfNS(5, 0); // 5 seconds, no count limit
247 bool c;
248
249 assert(tlfNS.empty());
250 assert(tlfNS.size() == 0);
251 assert(tlfNS.timeDepth() == 0);
252
253 c = tlfNS.add(new Foo("first"), TimeLimitFifo<Foo>::EnforceTimeDepth);
254 assert(c);
255 sleepMS(3000);
256 c = tlfNS.add(new Foo("second"), TimeLimitFifo<Foo>::EnforceTimeDepth);
257 assert(c);
258 sleepMS(3000);
259 c = tlfNS.add(new Foo("nope"), TimeLimitFifo<Foo>::EnforceTimeDepth);
260 assert(!c);
261 Foo* fp = tlfNS.getNext();
262 assert(fp->mVal == "first");
263 delete fp;
264 c = tlfNS.add(new Foo("third"), TimeLimitFifo<Foo>::EnforceTimeDepth);
265 assert(c);
266 }
267
268 {
269 TimeLimitFifo<Foo> tlfNS(5, 0); // 5 seconds, no count limit
270 bool c;
271
272 assert(tlfNS.empty());
273 assert(tlfNS.size() == 0);
274 assert(tlfNS.timeDepth() == 0);
275
276 for (int i = 0; i < 100; ++i)
277 {
278 c = tlfNS.add(new Foo(Data("element") + Data(i)), TimeLimitFifo<Foo>::EnforceTimeDepth);
279 assert(c);
280 }
281
282 sleepMS(6000);
283 c = tlfNS.add(new Foo("nope"), TimeLimitFifo<Foo>::EnforceTimeDepth);
284 assert(!c);
285
286 c = tlfNS.add(new Foo("yep"), TimeLimitFifo<Foo>::IgnoreTimeDepth);
287 assert(c);
288
289 assert(tlfNS.size() == 101);
290
291 while (!tlfNS.empty())
292 {
293 delete tlfNS.getNext();
294 }
295
296 c = tlfNS.add(new Foo("first"), TimeLimitFifo<Foo>::EnforceTimeDepth);
297 assert(c);
298 }
299
300 {
301 cerr << "!! Test reserved" << endl;
302
303 TimeLimitFifo<Foo> tlfNS(5, 10); // 5 seconds, limit 10 (2 reserved)
304 bool c;
305
306 assert(tlfNS.empty());
307 assert(tlfNS.size() == 0);
308 assert(tlfNS.timeDepth() == 0);
309
310 for (int i = 0; i < 8; ++i)
311 {
312 c = tlfNS.add(new Foo(Data("element") + Data(i)), TimeLimitFifo<Foo>::EnforceTimeDepth);
313 assert(c);
314 }
315
316 c = tlfNS.add(new Foo("nope"), TimeLimitFifo<Foo>::IgnoreTimeDepth);
317 assert(!c);
318
319 assert(tlfNS.size() == 8);
320
321 c = tlfNS.add(new Foo("yep"), TimeLimitFifo<Foo>::InternalElement);
322 assert(c);
323
324 c = tlfNS.add(new Foo("yepAgain"), TimeLimitFifo<Foo>::InternalElement);
325 assert(c);
326
327 c = tlfNS.add(new Foo("hard nope!"), TimeLimitFifo<Foo>::InternalElement);
328 assert(!c);
329
330 while (!tlfNS.empty())
331 {
332 delete tlfNS.getNext();
333 }
334
335 c = tlfNS.add(new Foo("first"), TimeLimitFifo<Foo>::EnforceTimeDepth);
336 assert(c);
337 }
338
339 {
340 cerr << "!! Test unlimited" << endl;
341
342 TimeLimitFifo<Foo> tlfNS(0, 0); // unlimited
343
344 bool c;
345
346 assert(tlfNS.empty());
347 assert(tlfNS.size() == 0);
348 assert(tlfNS.timeDepth() == 0);
349
350 for (int i = 0; i < 100; ++i)
351 {
352 c = tlfNS.add(new Foo(Data("element") + Data(i)), TimeLimitFifo<Foo>::EnforceTimeDepth);
353 assert(c);
354 sleepMS(1000);
355 }
356 }
357
358 {
359 cerr << "!! Test produce consumer" << endl;
360
361 TimeLimitFifo<Foo> tlfNS(20, 5000);
362 Producer prod(tlfNS);
363 Consumer cons(tlfNS);
364
365 cons.run();
366 prod.run();
367 #ifdef VERBOSE
368 cerr << "Producer and consumer threads are running" << endl;
369 #endif
370 prod.join();
371 #ifdef VERBOSE
372 cerr << "Producer thread finished" << endl;
373 #endif
374 cons.shutdown();
375 cons.join();
376 #ifdef VERBOSE
377 cerr << "Consumer thread finished" << endl;
378 #endif
379 }
380
381 {
382 cerr << "!! Test producers consumers" << endl;
383
384 TimeLimitFifo<Foo> tlfNS(20, 50000);
385
386 Producer prod1(tlfNS);
387 Producer prod2(tlfNS);
388 Producer prod3(tlfNS);
389 Producer prod4(tlfNS);
390 Producer prod5(tlfNS);
391 Producer prod6(tlfNS);
392 Producer prod7(tlfNS);
393 Producer prod8(tlfNS);
394 Producer prod9(tlfNS);
395 Producer prod10(tlfNS);
396
397 Consumer cons1(tlfNS);
398 Consumer cons2(tlfNS);
399 Consumer cons3(tlfNS);
400 Consumer cons4(tlfNS);
401 Consumer cons5(tlfNS);
402 Consumer cons6(tlfNS);
403 Consumer cons7(tlfNS);
404 Consumer cons8(tlfNS);
405 Consumer cons9(tlfNS);
406 Consumer cons10(tlfNS);
407
408
409 cons1.run();
410 cons2.run();
411 cons3.run();
412 cons4.run();
413 cons5.run();
414 cons6.run();
415 cons7.run();
416 cons8.run();
417 cons9.run();
418 cons10.run();
419
420 #ifdef VERBOSE
421 cerr << "before getNext(1000) " << Timer::getTimeMs() << endl;
422 #endif
423 tlfNS.getNext(1000);
424 #ifdef VERBOSE
425 cerr << "after getNext(1000) " << Timer::getTimeMs() << endl;
426 #endif
427 prod1.run();
428
429 #ifdef VERBOSE
430 cerr << "before getNext(1000) " << Timer::getTimeMs() << endl;
431 #endif
432 tlfNS.getNext(1000);
433 #ifdef VERBOSE
434 cerr << "after getNext(1000) " << Timer::getTimeMs() << endl;
435 #endif
436 prod2.run();
437 prod3.run();
438 prod4.run();
439 prod5.run();
440 prod6.run();
441 prod7.run();
442 prod8.run();
443 prod9.run();
444 prod10.run();
445
446 // Wait for producers to finish
447 prod1.join();
448 prod2.join();
449 prod3.join();
450 prod4.join();
451 prod5.join();
452 prod6.join();
453 prod7.join();
454 prod8.join();
455 prod9.join();
456 prod10.join();
457
458 // Give some time for consumers to finish consuming, before shutting down
459 sleepMS(1000);
460 }
461
462 cerr << "All OK" << endl;
463 return 0;
464 }
465
466 /* ====================================================================
467 * The Vovida Software License, Version 1.0
468 *
469 * Redistribution and use in source and binary forms, with or without
470 * modification, are permitted provided that the following conditions
471 * are met:
472 *
473 * 1. Redistributions of source code must retain the above copyright
474 * notice, this list of conditions and the following disclaimer.
475 *
476 * 2. Redistributions in binary form must reproduce the above copyright
477 * notice, this list of conditions and the following disclaimer in
478 * the documentation and/or other materials provided with the
479 * distribution.
480 *
481 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
482 * and "Vovida Open Communication Application Library (VOCAL)" must
483 * not be used to endorse or promote products derived from this
484 * software without prior written permission. For written
485 * permission, please contact vocal@vovida.org.
486 *
487 * 4. Products derived from this software may not be called "VOCAL", nor
488 * may "VOCAL" appear in their name, without prior written
489 * permission of Vovida Networks, Inc.
490 *
491 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
492 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
493 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
494 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
495 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
496 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
497 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
498 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
499 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
500 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
501 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
502 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
503 * DAMAGE.
504 *
505 * ====================================================================
506 *
507 * This software consists of voluntary contributions made by Vovida
508 * Networks, Inc. and many individuals on behalf of Vovida Networks,
509 * Inc. For more information on Vovida Networks, Inc., please see
510 * <http://www.vovida.org/>.
511 *
512 */

Properties

Name Value
svn:eol-style native

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27