$search
00001 /*************************************************************************** 00002 tag: Peter Soetens Mon Jan 10 15:59:51 CET 2005 buffers_test.cpp 00003 00004 buffers_test.cpp - description 00005 ------------------- 00006 begin : Mon January 10 2005 00007 copyright : (C) 2005 Peter Soetens 00008 email : peter.soetens@mech.kuleuven.ac.be 00009 00010 *************************************************************************** 00011 * * 00012 * This program is free software; you can redistribute it and/or modify * 00013 * it under the terms of the GNU General Public License as published by * 00014 * the Free Software Foundation; either version 2 of the License, or * 00015 * (at your option) any later version. * 00016 * * 00017 ***************************************************************************/ 00018 00019 #include "unit.hpp" 00020 00021 #include <iostream> 00022 #include <boost/scoped_ptr.hpp> 00023 00024 #include <internal/AtomicQueue.hpp> 00025 #include <internal/AtomicMWSRQueue.hpp> 00026 00027 #include <Activity.hpp> 00028 00029 #include <RTT.hpp> 00030 #include <base/Buffer.hpp> 00031 #include <internal/ListLockFree.hpp> 00032 #include <base/DataObject.hpp> 00033 #include <internal/TsPool.hpp> 00034 //#include <internal/SortedList.hpp> 00035 00036 #include <os/Thread.hpp> 00037 #include <rtt-config.h> 00038 00039 using namespace std; 00040 using namespace RTT; 00041 using namespace RTT::detail; 00042 00043 class Dummy { 00044 public: 00045 Dummy(double a = 0.0, double b =1.0, double c=2.0) 00046 :d1(a), d2(b), d3(c) {} 00047 double d1; 00048 double d2; 00049 double d3; 00050 bool operator==(const Dummy& d) const 00051 { 00052 return d.d1 == d1 && d.d2 == d2 && d.d3 == d3; 00053 } 00054 00055 bool operator!=(const Dummy& d) const 00056 { 00057 return d.d1 != d1 || d.d2 != d2 || d.d3 != d3; 00058 } 00059 00060 bool operator<(const Dummy& d) const 00061 { 00062 return d1+d2+d3 < d.d1 + d.d2 + d.d3; 00063 } 00064 /* 00065 volatile Dummy& operator=(const Dummy& d) volatile 00066 { 00067 d1 = d.d1; 00068 d2 = d.d2; 00069 d3 = d.d3; 00070 return *this; 00071 } 00072 */ 00073 }; 00074 00075 00076 typedef AtomicQueue<Dummy*> QueueType; 00077 typedef AtomicMWSRQueue<Dummy*> MWSRQueueType; 00078 00079 // Don't make queue size too large, we want to catch 00080 // overrun issues too. 00081 #define QS 10 00082 00083 class BuffersAQueueTest 00084 { 00085 public: 00086 AtomicQueue<Dummy*>* aqueue; 00087 ThreadInterface* athread; 00088 ThreadInterface* bthread; 00089 ListLockFree<Dummy>* listlockfree; 00090 00091 BuffersAQueueTest() 00092 { 00093 aqueue = new AtomicQueue<Dummy*>(QS); 00094 listlockfree = new ListLockFree<Dummy>(10, 4); 00095 } 00096 ~BuffersAQueueTest(){ 00097 aqueue->clear(); 00098 delete aqueue; 00099 delete listlockfree; 00100 } 00101 }; 00102 00103 class BuffersAtomicMWSRQueueTest 00104 { 00105 public: 00106 AtomicMWSRQueue<Dummy*>* aqueue; 00107 00108 BuffersAtomicMWSRQueueTest() 00109 { 00110 aqueue = new AtomicMWSRQueue<Dummy*>(QS); 00111 } 00112 ~BuffersAtomicMWSRQueueTest(){ 00113 aqueue->clear(); 00114 delete aqueue; 00115 } 00116 }; 00117 00118 class BuffersDataFlowTest 00119 { 00120 public: 00121 BufferInterface<Dummy>* buffer; 00122 BufferInterface<Dummy>* circular; 00123 DataObjectInterface<Dummy>* dataobj; 00124 00125 BufferLockFree<Dummy>* lockfree; 00126 BufferLocked<Dummy>* locked; 00127 BufferUnSync<Dummy>* unsync; 00128 00129 BufferLockFree<Dummy>* clockfree; 00130 BufferLocked<Dummy>* clocked; 00131 BufferUnSync<Dummy>* cunsync; 00132 00133 DataObjectLocked<Dummy>* dlocked; 00134 DataObjectLockFree<Dummy>* dlockfree; 00135 DataObjectUnSync<Dummy>* dunsync; 00136 00137 ThreadInterface* athread; 00138 ThreadInterface* bthread; 00139 00140 void testBuf(); 00141 void testCirc(); 00142 void testDObj(); 00143 00144 BuffersDataFlowTest() 00145 { 00146 // clasical variants 00147 lockfree = new BufferLockFree<Dummy>(QS); 00148 locked = new BufferLocked<Dummy>(QS); 00149 unsync = new BufferUnSync<Dummy>(QS); 00150 00151 // circular variants. 00152 clockfree = new BufferLockFree<Dummy>(QS,Dummy(), true); 00153 clocked = new BufferLocked<Dummy>(QS,Dummy(), true); 00154 cunsync = new BufferUnSync<Dummy>(QS,Dummy(), true); 00155 00156 dlockfree = new DataObjectLockFree<Dummy>(); 00157 dlocked = new DataObjectLocked<Dummy>(); 00158 dunsync = new DataObjectUnSync<Dummy>(); 00159 00160 // defaults 00161 buffer = lockfree; 00162 dataobj = dlockfree; 00163 } 00164 00165 ~BuffersDataFlowTest(){ 00166 delete lockfree; 00167 delete locked; 00168 delete unsync; 00169 delete clockfree; 00170 delete clocked; 00171 delete cunsync; 00172 delete dlockfree; 00173 delete dlocked; 00174 delete dunsync; 00175 } 00176 }; 00177 00178 void BuffersDataFlowTest::testBuf() 00179 { 00185 Dummy* d = new Dummy; 00186 Dummy* c = new Dummy(2.0, 1.0, 0.0); 00187 Dummy r; 00188 00189 BOOST_CHECK( buffer->Pop(r) == false ); 00190 00191 BOOST_CHECK( buffer->Push( *d ) ); 00192 BOOST_CHECK( buffer->Pop(r) ); 00193 BOOST_CHECK( r == *d ); 00194 00195 BOOST_CHECK( buffer->Push( *c ) ); 00196 BOOST_CHECK( buffer->Pop(r) ); 00197 BOOST_CHECK( r == *c ); 00198 00199 BOOST_CHECK( buffer->Push( *d ) ); 00200 BOOST_CHECK( buffer->Push( *c ) ); 00201 BOOST_CHECK( buffer->Push( *d ) ); 00202 BOOST_CHECK( buffer->Push( *c ) ); 00203 BOOST_CHECK( buffer->Push( *d ) ); 00204 BOOST_CHECK( buffer->Push( *c ) ); 00205 BOOST_CHECK( buffer->Push( *d ) ); 00206 BOOST_CHECK( buffer->Push( *c ) ); 00207 BOOST_CHECK( buffer->Push( *d ) ); 00208 BOOST_CHECK( buffer->Push( *c ) ); 00209 BOOST_CHECK( buffer->Push( *c ) == false ); 00210 BOOST_CHECK( buffer->Push( *c ) == false ); 00211 BOOST_CHECK( buffer->Push( *c ) == false ); 00212 BOOST_CHECK( buffer->Push( *c ) == false ); 00213 BOOST_CHECK( buffer->Push( *c ) == false ); 00214 BOOST_CHECK( buffer->Push( *c ) == false ); 00215 BOOST_CHECK( buffer->Push( *c ) == false ); 00216 BOOST_CHECK( buffer->Push( *c ) == false ); 00217 BOOST_CHECK( buffer->Push( *c ) == false ); 00218 BOOST_CHECK( buffer->Push( *c ) == false ); 00219 BOOST_CHECK( buffer->Push( *c ) == false ); 00220 BOOST_CHECK( buffer->Push( *c ) == false ); 00221 BOOST_CHECK( buffer->Pop(r) ); 00222 BOOST_CHECK( r == *d ); 00223 BOOST_CHECK( buffer->Pop(r) ); 00224 BOOST_CHECK( r == *c ); 00225 BOOST_CHECK( buffer->Pop(r) ); 00226 BOOST_CHECK( r == *d ); 00227 BOOST_CHECK( buffer->Pop(r) ); 00228 BOOST_CHECK( r == *c ); 00229 BOOST_CHECK( buffer->Pop(r) ); 00230 BOOST_CHECK( r == *d ); 00231 00232 // start writing again half-way 00233 BOOST_CHECK( buffer->Push( *d ) ); 00234 BOOST_CHECK( buffer->Push( *c ) ); 00235 BOOST_CHECK( buffer->Push( *d ) ); 00236 BOOST_CHECK( buffer->Push( *c ) ); 00237 BOOST_CHECK( buffer->Push( *d ) ); 00238 00239 BOOST_CHECK( buffer->Pop(r) ); 00240 BOOST_CHECK( r == *c ); 00241 BOOST_CHECK( buffer->Pop(r) ); 00242 BOOST_CHECK( r == *d ); 00243 BOOST_CHECK( buffer->Pop(r) ); 00244 BOOST_CHECK( r == *c ); 00245 BOOST_CHECK( buffer->Pop(r) ); 00246 BOOST_CHECK( r == *d ); 00247 BOOST_CHECK( buffer->Pop(r) ); 00248 BOOST_CHECK( r == *c ); 00249 BOOST_CHECK( buffer->Pop(r) ); 00250 BOOST_CHECK( r == *d ); 00251 BOOST_CHECK( buffer->Pop(r) ); 00252 BOOST_CHECK( r == *c ); 00253 BOOST_CHECK( buffer->Pop(r) ); 00254 BOOST_CHECK( r == *d ); 00255 BOOST_CHECK( buffer->Pop(r) ); 00256 BOOST_CHECK( r == *c ); 00257 BOOST_CHECK( buffer->Pop(r) ); 00258 BOOST_CHECK( r == *d ); 00259 00260 BOOST_CHECK( buffer->Pop(r) == false ); 00261 BOOST_CHECK( buffer->Pop(r) == false ); 00262 BOOST_CHECK( buffer->Pop(r) == false ); 00263 BOOST_CHECK( buffer->Pop(r) == false ); 00264 BOOST_CHECK( buffer->Pop(r) == false ); 00265 BOOST_CHECK( buffer->Pop(r) == false ); 00266 BOOST_CHECK( buffer->Pop(r) == false ); 00267 BOOST_CHECK( buffer->Pop(r) == false ); 00268 BOOST_CHECK( buffer->Pop(r) == false ); 00269 BOOST_CHECK( buffer->Pop(r) == false ); 00270 BOOST_CHECK( buffer->Pop(r) == false ); 00271 00272 BOOST_CHECK( buffer->Push( *c ) ); 00273 BOOST_CHECK( buffer->Push( *d ) ); 00274 BOOST_CHECK( buffer->Push( *c ) ); 00275 BOOST_CHECK( buffer->Push( *d ) ); 00276 BOOST_CHECK( buffer->Push( *c ) ); 00277 00278 std::vector<Dummy> v; 00279 BOOST_CHECK( 5 == buffer->Pop(v) ); 00280 BOOST_CHECK( v[0] == *c ); 00281 BOOST_CHECK( v[1] == *d ); 00282 BOOST_CHECK( v[2] == *c ); 00283 BOOST_CHECK( v[3] == *d ); 00284 BOOST_CHECK( v[4] == *c ); 00285 00286 BufferBase::size_type sz = 10; 00287 BOOST_CHECK( buffer->Push( *c ) ); 00288 BOOST_CHECK( buffer->Push( *d ) ); 00289 BOOST_CHECK( buffer->Push( v ) == (int)v.size() ); 00290 BOOST_CHECK( buffer->Push( *c ) ); 00291 BOOST_CHECK( buffer->Push( *d ) ); 00292 BOOST_CHECK( buffer->Push( v ) == 1 ); 00293 BOOST_CHECK( buffer->Push( v ) == 0 ); 00294 BOOST_CHECK( buffer->Push( v ) == 0 ); 00295 BOOST_CHECK( buffer->Push( v ) == 0 ); 00296 BOOST_CHECK( buffer->Push( v ) == 0 ); 00297 BOOST_CHECK( buffer->Push( v ) == 0 ); 00298 BOOST_CHECK( buffer->Push( v ) == 0 ); 00299 BOOST_CHECK( buffer->Push( v ) == 0 ); 00300 BOOST_CHECK( buffer->Push( v ) == 0 ); 00301 BOOST_CHECK( buffer->Push( v ) == 0 ); 00302 BOOST_CHECK( buffer->Push( v ) == 0 ); 00303 BOOST_CHECK( buffer->Push( v ) == 0 ); 00304 BOOST_CHECK( buffer->Push( v ) == 0 ); 00305 BOOST_REQUIRE_EQUAL( sz, buffer->Pop(v) ); 00306 BOOST_CHECK( v[0] == *c ); 00307 BOOST_CHECK( v[1] == *d ); 00308 BOOST_CHECK( v[2] == *c ); 00309 BOOST_CHECK( v[3] == *d ); 00310 BOOST_CHECK( v[4] == *c ); 00311 BOOST_CHECK( v[5] == *d ); 00312 BOOST_CHECK( v[6] == *c ); 00313 BOOST_CHECK( v[7] == *c ); 00314 BOOST_CHECK( v[8] == *d ); 00315 //BOOST_CHECK( v[9] == *c ); 00316 BOOST_CHECK( 0 == buffer->Pop(v) ); 00317 delete d; 00318 delete c; 00319 } 00320 00321 void BuffersDataFlowTest::testCirc() 00322 { 00328 Dummy* d = new Dummy; 00329 Dummy* c = new Dummy(2.0, 1.0, 0.0); 00330 Dummy r; 00331 00332 BOOST_CHECK( circular->Pop(r) == false ); 00333 00334 BOOST_CHECK( circular->Push( *d ) ); 00335 BOOST_CHECK( circular->Pop(r) ); 00336 BOOST_CHECK( r == *d ); 00337 00338 BOOST_CHECK( circular->Push( *c ) ); 00339 BOOST_CHECK( circular->Pop(r) ); 00340 BOOST_CHECK( r == *c ); 00341 00342 BOOST_CHECK( circular->Push( *d ) ); 00343 BOOST_CHECK( circular->Push( *c ) ); 00344 BOOST_CHECK( circular->Push( *d ) ); 00345 BOOST_CHECK( circular->Push( *c ) ); 00346 BOOST_CHECK( circular->Push( *d ) ); 00347 BOOST_CHECK( circular->Push( *c ) ); 00348 BOOST_CHECK( circular->Push( *d ) ); 00349 BOOST_CHECK( circular->Push( *c ) ); 00350 BOOST_CHECK( circular->Push( *d ) ); 00351 BOOST_CHECK( circular->Push( *c ) ); // oldest item at end of Push series. 00352 BOOST_CHECK( circular->Push( *d ) ); 00353 BOOST_CHECK( circular->Push( *c ) ); 00354 BOOST_CHECK( circular->Push( *d ) ); 00355 BOOST_CHECK( circular->Push( *c ) ); 00356 BOOST_CHECK( circular->Push( *d ) ); 00357 BOOST_CHECK( circular->Push( *c ) ); 00358 BOOST_CHECK( circular->Push( *d ) ); 00359 BOOST_CHECK( circular->Push( *c ) ); 00360 BOOST_CHECK( circular->Push( *d ) ); 00361 BOOST_CHECK( circular->Pop(r) ); 00362 BOOST_CHECK( r == *c ); 00363 BOOST_CHECK( circular->Pop(r) ); 00364 BOOST_CHECK( r == *d ); 00365 BOOST_CHECK( circular->Pop(r) ); 00366 BOOST_CHECK( r == *c ); 00367 BOOST_CHECK( circular->Pop(r) ); 00368 BOOST_CHECK( r == *d ); 00369 BOOST_CHECK( circular->Pop(r) ); 00370 BOOST_CHECK( r == *c ); 00371 00372 // start writing again half-way 00373 BOOST_CHECK( circular->Push( *d ) ); 00374 BOOST_CHECK( circular->Push( *c ) ); 00375 BOOST_CHECK( circular->Push( *d ) ); 00376 BOOST_CHECK( circular->Push( *c ) ); 00377 BOOST_CHECK( circular->Push( *d ) ); 00378 00379 BOOST_CHECK( circular->Pop(r) ); 00380 BOOST_CHECK( r == *d ); 00381 BOOST_CHECK( circular->Pop(r) ); 00382 BOOST_CHECK( r == *c ); 00383 BOOST_CHECK( circular->Pop(r) ); 00384 BOOST_CHECK( r == *d ); 00385 BOOST_CHECK( circular->Pop(r) ); 00386 BOOST_CHECK( r == *c ); 00387 BOOST_CHECK( circular->Pop(r) ); 00388 BOOST_CHECK( r == *d ); 00389 BOOST_CHECK( circular->Pop(r) ); 00390 BOOST_CHECK( r == *d ); 00391 BOOST_CHECK( circular->Pop(r) ); 00392 BOOST_CHECK( r == *c ); 00393 BOOST_CHECK( circular->Pop(r) ); 00394 BOOST_CHECK( r == *d ); 00395 BOOST_CHECK( circular->Pop(r) ); 00396 BOOST_CHECK( r == *c ); 00397 BOOST_CHECK( circular->Pop(r) ); 00398 BOOST_CHECK( r == *d ); 00399 00400 BOOST_CHECK( circular->Pop(r) == false ); 00401 BOOST_CHECK( circular->Pop(r) == false ); 00402 BOOST_CHECK( circular->Pop(r) == false ); 00403 BOOST_CHECK( circular->Pop(r) == false ); 00404 BOOST_CHECK( circular->Pop(r) == false ); 00405 BOOST_CHECK( circular->Pop(r) == false ); 00406 BOOST_CHECK( circular->Pop(r) == false ); 00407 BOOST_CHECK( circular->Pop(r) == false ); 00408 BOOST_CHECK( circular->Pop(r) == false ); 00409 BOOST_CHECK( circular->Pop(r) == false ); 00410 BOOST_CHECK( circular->Pop(r) == false ); 00411 00412 BOOST_CHECK( circular->Push( *c ) ); 00413 BOOST_CHECK( circular->Push( *d ) ); 00414 BOOST_CHECK( circular->Push( *c ) ); 00415 BOOST_CHECK( circular->Push( *d ) ); 00416 BOOST_CHECK( circular->Push( *c ) ); 00417 00418 std::vector<Dummy> v; 00419 BOOST_CHECK( 5 == circular->Pop(v) ); 00420 BOOST_CHECK( v[0] == *c ); 00421 BOOST_CHECK( v[1] == *d ); 00422 BOOST_CHECK( v[2] == *c ); 00423 BOOST_CHECK( v[3] == *d ); 00424 BOOST_CHECK( v[4] == *c ); 00425 00426 BufferBase::size_type sz = 10; 00427 BOOST_CHECK( circular->Push( *c ) ); 00428 BOOST_CHECK( circular->Push( *d ) ); 00429 BOOST_CHECK( circular->Push( v ) == (int)v.size() ); 00430 BOOST_CHECK( circular->Push( *c ) ); 00431 BOOST_CHECK( circular->Push( *d ) ); 00432 BOOST_CHECK( circular->Push( v ) == (int)v.size() ); 00433 BOOST_CHECK( circular->Push( v ) == (int)v.size() ); 00434 BOOST_CHECK( circular->Push( v ) == (int)v.size() ); 00435 BOOST_CHECK( circular->Push( v ) == (int)v.size() ); 00436 BOOST_CHECK( circular->Push( v ) == (int)v.size() ); 00437 BOOST_REQUIRE_EQUAL( sz, circular->Pop(v) ); 00438 BOOST_CHECK( v[0] == *c ); 00439 BOOST_CHECK( v[1] == *d ); 00440 BOOST_CHECK( v[2] == *c ); 00441 BOOST_CHECK( v[3] == *d ); 00442 BOOST_CHECK( v[4] == *c ); 00443 BOOST_CHECK( v[5] == *c ); 00444 BOOST_CHECK( v[6] == *d ); 00445 BOOST_CHECK( v[7] == *c ); 00446 BOOST_CHECK( v[8] == *d ); 00447 BOOST_CHECK( v[9] == *c ); 00448 BOOST_CHECK( 0 == circular->Pop(v) ); 00449 delete d; 00450 delete c; 00451 } 00452 00453 void BuffersDataFlowTest::testDObj() 00454 { 00455 Dummy* c = new Dummy(2.0, 1.0, 0.0); 00456 Dummy d; 00457 dataobj->Set( *c ); 00458 BOOST_REQUIRE_EQUAL( *c, dataobj->Get() ); 00459 int i = 0; 00460 while ( i != 3.5*dlockfree->MAX_THREADS ) { 00461 dataobj->Set( *c ); 00462 dataobj->Set( d ); 00463 ++i; 00464 } 00465 BOOST_REQUIRE_EQUAL( d , dataobj->Get() ); 00466 BOOST_REQUIRE_EQUAL( d , dataobj->Get() ); 00467 00468 delete c; 00469 } 00470 00471 class BuffersMPoolTest 00472 { 00473 public: 00474 00475 ThreadInterface* athread; 00476 ThreadInterface* bthread; 00477 00478 TsPool<Dummy>* mpool; 00479 TsPool<std::vector<Dummy> >* vpool; 00480 00481 BuffersMPoolTest() 00482 { 00483 mpool = new TsPool<Dummy>(QS); 00484 vpool = new TsPool<std::vector<Dummy> >(QS, std::vector<Dummy>(QS) ); 00485 } 00486 00487 ~BuffersMPoolTest(){ 00488 delete mpool; 00489 delete vpool; 00490 } 00491 }; 00492 00493 00494 std::ostream& operator<<( std::ostream& os, const Dummy& d ) { 00495 os << "(" << d.d1 <<","<<d.d2<<","<<d.d3<<")"; 00496 return os; 00497 } 00498 void addOne(Dummy& d) 00499 { 00500 ++d.d1; 00501 ++d.d2; 00502 ++d.d3; 00503 } 00504 00505 void subOne(Dummy& d) 00506 { 00507 --d.d1; 00508 --d.d2; 00509 --d.d3; 00510 } 00511 00512 00513 struct LLFWorker : public RunnableInterface 00514 { 00515 volatile bool stop; 00516 typedef ListLockFree<Dummy> T; 00517 T* mlst; 00518 int i; 00519 int appends; 00520 int erases; 00521 LLFWorker(T* l ) : stop(false), mlst(l), i(1) {} 00522 bool initialize() { 00523 stop = false; i = 1; 00524 appends = 0; erases = 0; 00525 return true; 00526 } 00527 void step() { 00528 while (stop == false ) { 00529 //cout << "Appending, i="<<i<<endl; 00530 while ( mlst->append( Dummy(i,i,i) ) ) { ++i; ++appends; } 00531 //cout << "Erasing, i="<<i<<endl; 00532 while ( mlst->erase( Dummy(i-1,i-1,i-1) ) ) { --i; ++erases; } 00533 } 00534 //cout << "Stopping, i="<<i<<endl; 00535 } 00536 00537 void finalize() {} 00538 00539 bool breakLoop() { 00540 stop = true; 00541 return true; 00542 } 00543 }; 00544 00545 struct LLFGrower : public RunnableInterface 00546 { 00547 volatile bool stop; 00548 typedef ListLockFree<Dummy> T; 00549 T* mlst; 00550 int i; 00551 LLFGrower(T* l ) : stop(false), mlst(l), i(1) {} 00552 bool initialize() { 00553 stop = false; i = 1; 00554 return true; 00555 } 00556 void step() { 00557 // stress growing of list during append/erase. 00558 while (stop == false && i < 2500 ) { 00559 // reserve is quite slow. 00560 mlst->reserve(i); 00561 ++i; 00562 } 00563 } 00564 00565 void finalize() {} 00566 00567 bool breakLoop() { 00568 stop = true; 00569 return true; 00570 } 00571 }; 00572 00576 template<class T> 00577 struct AQWorker : public RunnableInterface 00578 { 00579 static os::Mutex m; 00580 bool stop; 00581 T* mlst; 00582 int appends; 00583 int erases; 00584 Dummy* orig; 00585 AQWorker(T* l ) : stop(false), mlst(l),appends(0), erases(0) { 00586 orig = new Dummy( 1,2,3); 00587 } 00588 ~AQWorker() { 00589 delete orig; 00590 } 00591 bool initialize() { 00592 stop = false; 00593 return true; 00594 } 00595 void step() { 00596 Dummy* d = orig; 00597 while (stop == false ) { 00598 //cout << "Appending, i="<<i<<endl; 00599 if ( mlst->enqueue( d ) ) { ++appends; } 00600 //cout << "Erasing, i="<<i<<endl; 00601 if ( mlst->dequeue( d ) ) { 00602 if( *d != *orig) { 00603 os::MutexLock lock(m); 00604 assert(*d == *orig); // exercise reading returned memory. 00605 } 00606 ++erases; 00607 } 00608 } 00609 //cout << "Stopping, i="<<i<<endl; 00610 } 00611 00612 void finalize() {} 00613 00614 bool breakLoop() { 00615 stop = true; 00616 return true; 00617 } 00618 }; 00619 00620 template<class T> 00621 os::Mutex AQWorker<T>::m; 00622 00627 template<class T> 00628 struct AQGrower : public RunnableInterface 00629 { 00630 volatile bool stop; 00631 T* mlst; 00632 int appends; 00633 Dummy* orig; 00634 AQGrower(T* l ) : stop(false), mlst(l), appends(0) { 00635 orig = new Dummy( 1,2,3); 00636 } 00637 ~AQGrower() { 00638 delete orig; 00639 } 00640 bool initialize() { 00641 stop = false; 00642 return true; 00643 } 00644 void step() { 00645 // stress full queue 00646 Dummy* d = orig; 00647 while (stop == false ) { 00648 if ( mlst->enqueue(d) ) { 00649 ++appends; 00650 } 00651 } 00652 } 00653 00654 void finalize() {} 00655 00656 bool breakLoop() { 00657 stop = true; 00658 return true; 00659 } 00660 }; 00661 00666 template<class T> 00667 struct AQEater : public RunnableInterface 00668 { 00669 volatile bool stop; 00670 T* mlst; 00671 int erases; 00672 AQEater(T* l ) : stop(false), mlst(l), erases(0) {} 00673 bool initialize() { 00674 stop = false; 00675 return true; 00676 } 00677 void step() { 00678 // stress full queue 00679 Dummy* d; 00680 while (stop == false ) { 00681 if ( mlst->dequeue(d) ) { 00682 //if( *d != *orig) 00683 // BOOST_CHECK_EQUAL(*d, *orig); // exercise reading returned memory. 00684 ++erases; 00685 } 00686 } 00687 } 00688 00689 void finalize() {} 00690 00691 bool breakLoop() { 00692 stop = true; 00693 return true; 00694 } 00695 }; 00696 00697 00698 BOOST_FIXTURE_TEST_SUITE( BuffersAtomicTestSuite, BuffersAQueueTest ) 00699 00700 BOOST_AUTO_TEST_CASE( testAtomicQueue ) 00701 { 00705 Dummy* d = new Dummy(); 00706 Dummy* c = d; 00707 00708 BOOST_REQUIRE_EQUAL( AtomicQueue<Dummy*>::size_type(QS), aqueue->capacity() ); 00709 BOOST_REQUIRE_EQUAL( AtomicQueue<Dummy*>::size_type(0), aqueue->size() ); 00710 BOOST_CHECK( aqueue->isFull() == false ); 00711 BOOST_CHECK( aqueue->isEmpty() == true ); 00712 BOOST_CHECK( aqueue->dequeue(c) == false ); 00713 BOOST_CHECK( c == d ); 00714 00715 for ( int i = 0; i < QS; ++i) { 00716 BOOST_CHECK( aqueue->enqueue( d ) == true); 00717 BOOST_REQUIRE_EQUAL( AtomicQueue<Dummy*>::size_type(i+1), aqueue->size() ); 00718 } 00719 BOOST_REQUIRE_EQUAL( AtomicQueue<Dummy*>::size_type(QS), aqueue->capacity() ); 00720 BOOST_CHECK( aqueue->isFull() == true ); 00721 BOOST_CHECK( aqueue->isEmpty() == false ); 00722 BOOST_CHECK( aqueue->enqueue( d ) == false ); 00723 BOOST_REQUIRE_EQUAL( AtomicQueue<Dummy*>::size_type(QS), aqueue->size() ); 00724 00725 aqueue->dequeue( d ); 00726 BOOST_CHECK( aqueue->isFull() == false ); 00727 BOOST_REQUIRE_EQUAL( AtomicQueue<Dummy*>::size_type(QS-1), aqueue->size() ); 00728 00729 for ( int i = 0; i < QS - 1 ; ++i) { 00730 BOOST_CHECK( aqueue->dequeue( d ) == true); 00731 BOOST_REQUIRE_EQUAL( AtomicQueue<Dummy*>::size_type(QS - 2 - i), aqueue->size() ); 00732 } 00733 BOOST_CHECK( aqueue->isFull() == false ); 00734 BOOST_CHECK( aqueue->isEmpty() == true ); 00735 00736 delete d; 00737 } 00738 BOOST_AUTO_TEST_SUITE_END() 00739 00740 BOOST_FIXTURE_TEST_SUITE( BuffersMWSRQueueTestSuite, BuffersAtomicMWSRQueueTest ) 00741 00742 BOOST_AUTO_TEST_CASE( testAtomicMWSRQueue ) 00743 { 00747 Dummy* d = new Dummy(); 00748 Dummy* c = d; 00749 00750 BOOST_REQUIRE_EQUAL( AtomicQueue<Dummy*>::size_type(QS), aqueue->capacity() ); 00751 BOOST_REQUIRE_EQUAL( AtomicQueue<Dummy*>::size_type(0), aqueue->size() ); 00752 BOOST_CHECK( aqueue->isFull() == false ); 00753 BOOST_CHECK( aqueue->isEmpty() == true ); 00754 BOOST_CHECK( aqueue->dequeue(c) == false ); 00755 BOOST_CHECK( c == d ); 00756 00757 for ( int i = 0; i < QS; ++i) { 00758 BOOST_CHECK( aqueue->enqueue( d ) == true); 00759 BOOST_REQUIRE_EQUAL( AtomicQueue<Dummy*>::size_type(i+1), aqueue->size() ); 00760 BOOST_CHECK( d ); 00761 } 00762 BOOST_REQUIRE_EQUAL( AtomicQueue<Dummy*>::size_type(QS), aqueue->capacity() ); 00763 BOOST_CHECK( aqueue->isFull() == true ); 00764 BOOST_CHECK( aqueue->isEmpty() == false ); 00765 BOOST_CHECK( aqueue->enqueue( d ) == false ); 00766 BOOST_REQUIRE_EQUAL( AtomicQueue<Dummy*>::size_type(QS), aqueue->size() ); 00767 d = 0; 00768 aqueue->dequeue( d ); 00769 BOOST_CHECK( d ); // not null 00770 BOOST_CHECK( aqueue->isFull() == false ); 00771 BOOST_REQUIRE_EQUAL( AtomicQueue<Dummy*>::size_type(QS-1), aqueue->size() ); 00772 00773 for ( int i = 0; i < QS - 1 ; ++i) { 00774 BOOST_CHECK( aqueue->dequeue( d ) == true); 00775 BOOST_REQUIRE_EQUAL( AtomicQueue<Dummy*>::size_type(QS - 2 - i), aqueue->size() ); 00776 BOOST_CHECK( d ); 00777 } 00778 BOOST_CHECK( aqueue->isFull() == false ); 00779 BOOST_CHECK( aqueue->isEmpty() == true ); 00780 BOOST_CHECK( aqueue->dequeue(d) == false ); 00781 BOOST_CHECK( d ); // not null 00782 00783 delete d; 00784 } 00785 00786 BOOST_AUTO_TEST_SUITE_END() 00787 00788 BOOST_FIXTURE_TEST_SUITE( BuffersDataFlowTestSuite, BuffersDataFlowTest ) 00789 00790 BOOST_AUTO_TEST_CASE( testBufLockFree ) 00791 { 00792 buffer = lockfree; 00793 circular = clockfree; 00794 testBuf(); 00795 testCirc(); 00796 } 00797 00798 BOOST_AUTO_TEST_CASE( testBufLocked ) 00799 { 00800 buffer = locked; 00801 circular = clocked; 00802 testBuf(); 00803 testCirc(); 00804 } 00805 00806 BOOST_AUTO_TEST_CASE( testBufUnsync ) 00807 { 00808 buffer = unsync; 00809 circular = cunsync; 00810 testBuf(); 00811 testCirc(); 00812 } 00813 00814 BOOST_AUTO_TEST_CASE( testDObjLockFree ) 00815 { 00816 dataobj = dlockfree; 00817 testDObj(); 00818 } 00819 00820 BOOST_AUTO_TEST_CASE( testDObjLocked ) 00821 { 00822 dataobj = dlocked; 00823 testDObj(); 00824 } 00825 00826 BOOST_AUTO_TEST_CASE( testDObjUnSync ) 00827 { 00828 dataobj = dunsync; 00829 testDObj(); 00830 } 00831 00832 BOOST_AUTO_TEST_SUITE_END() 00833 BOOST_FIXTURE_TEST_SUITE( BuffersMPoolTestSuite, BuffersMPoolTest ) 00834 00835 BOOST_AUTO_TEST_CASE( testMemoryPool ) 00836 { 00837 // Test initial conditions. 00838 TsPool<Dummy>::size_type sz = QS; 00839 // Capacity test 00840 BOOST_REQUIRE_EQUAL( sz, mpool->capacity() ); 00841 BOOST_REQUIRE_EQUAL( sz, vpool->capacity() ); 00842 BOOST_CHECK_EQUAL( sz, mpool->size()); 00843 BOOST_CHECK_EQUAL( sz, vpool->size()); 00844 00845 // test default initialiser: 00846 for (TsPool<Dummy>::size_type i = 0; i <3*sz; ++i ) { 00847 // MemoryPool: 00848 std::vector<Dummy>* v = vpool->allocate(); 00849 BOOST_CHECK_EQUAL( sz - 1, vpool->size()); 00850 std::vector<Dummy>::size_type szv = QS; 00851 BOOST_REQUIRE_EQUAL( szv, v->size() ); 00852 BOOST_REQUIRE_EQUAL( szv, v->capacity() ); 00853 BOOST_CHECK(vpool->deallocate( v )); 00854 BOOST_CHECK_EQUAL( sz, vpool->size()); 00855 } 00856 BOOST_CHECK_EQUAL( vpool->size(), QS); 00857 00858 // test Allocation. 00859 std::vector<Dummy*> mpv; 00860 // MemoryPool: 00861 for (TsPool<Dummy>::size_type i = 0; i <sz; ++i ) { 00862 mpv.push_back( mpool->allocate() ); 00863 BOOST_CHECK_EQUAL( sz - i - 1, mpool->size()); 00864 BOOST_CHECK( mpv.back() ); 00865 BOOST_REQUIRE_EQUAL( sz, mpool->capacity() ); 00866 } 00867 BOOST_CHECK_EQUAL( mpool->size(), 0); 00868 BOOST_CHECK_EQUAL( mpool->allocate(), (Dummy*)0 ); 00869 for (TsPool<Dummy>::size_type i = 0; i <sz; ++i ) { 00870 BOOST_CHECK_EQUAL( i , mpool->size()); 00871 BOOST_CHECK(mpool->deallocate( mpv.front() )); 00872 BOOST_CHECK_EQUAL( i + 1, mpool->size()); 00873 mpv.erase( mpv.begin() ); 00874 BOOST_REQUIRE_EQUAL( sz, mpool->capacity() ); 00875 } 00876 BOOST_CHECK_EQUAL( mpv.size(), 0 ); 00877 BOOST_CHECK_EQUAL( mpool->size(), QS); 00878 } 00879 00880 #if 0 00881 BOOST_AUTO_TEST_CASE( testSortedList ) 00882 { 00883 // 7 elements. 00884 mslist->reserve(7); 00885 BOOST_CHECK( mslist->empty() ); 00886 00887 // empty list has no keys. 00888 BOOST_CHECK( mslist->hasKey(Dummy()) == false ); 00889 00890 // empty list fails to erase key. 00891 BOOST_CHECK( mslist->erase(Dummy()) == false ); 00892 00893 // insert element once 00894 BOOST_CHECK( mslist->insert(Dummy(1,2,1)) == true ); 00895 BOOST_CHECK( mslist->hasKey(Dummy(1,2,1)) == true ); 00896 00897 BOOST_CHECK( mslist->insert(Dummy(1,2,1)) == false ); 00898 BOOST_CHECK( mslist->hasKey(Dummy(1,2,1)) == true ); 00899 00900 // erase element once 00901 BOOST_CHECK( mslist->erase(Dummy(1,2,1)) == true ); 00902 BOOST_CHECK( mslist->hasKey(Dummy(1,2,1)) == false ); 00903 BOOST_CHECK( mslist->erase(Dummy(1,2,1)) == false ); 00904 BOOST_CHECK( mslist->hasKey(Dummy(1,2,1)) == false ); 00905 00906 BOOST_CHECK( mslist->insert(Dummy(1,2,1)) == true ); 00907 BOOST_CHECK( mslist->insert(Dummy(1,2,2)) == true ); 00908 BOOST_CHECK( mslist->insert(Dummy(1,2,3)) == true ); 00909 BOOST_CHECK( mslist->insert(Dummy(1,2,4)) == true ); 00910 BOOST_CHECK( mslist->insert(Dummy(1,2,5)) == true ); 00911 BOOST_CHECK( mslist->insert(Dummy(1,2,6)) == true ); 00912 BOOST_CHECK( mslist->insert(Dummy(1,2,7)) == true ); 00913 00914 BOOST_CHECK( mslist->hasKey(Dummy(1,2,4)) == true ); 00915 BOOST_CHECK( mslist->hasKey(Dummy(1,2,7)) == true ); 00916 00917 BOOST_CHECK( mslist->erase(Dummy(1,2,7)) == true ); 00918 BOOST_CHECK( mslist->hasKey(Dummy(1,2,7)) == false ); 00919 00920 BOOST_CHECK( mslist->erase(Dummy(1,2,4)) == true ); 00921 BOOST_CHECK( mslist->hasKey(Dummy(1,2,4)) == false ); 00922 00923 mslist->applyOnData( &addOne ); 00924 BOOST_CHECK( mslist->hasKey(Dummy(2,3,2)) == true ); 00925 BOOST_CHECK( mslist->hasKey(Dummy(2,3,3)) == true ); 00926 BOOST_CHECK( mslist->hasKey(Dummy(2,3,4)) == true ); 00927 BOOST_CHECK( mslist->hasKey(Dummy(2,3,6)) == true ); 00928 BOOST_CHECK( mslist->hasKey(Dummy(2,3,7)) == true ); 00929 00930 mslist->applyOnData( &subOne ); 00931 BOOST_CHECK( mslist->hasKey(Dummy(1,2,1)) == true ); 00932 BOOST_CHECK( mslist->hasKey(Dummy(1,2,2)) == true ); 00933 BOOST_CHECK( mslist->hasKey(Dummy(1,2,3)) == true ); 00934 BOOST_CHECK( mslist->hasKey(Dummy(1,2,5)) == true ); 00935 BOOST_CHECK( mslist->hasKey(Dummy(1,2,6)) == true ); 00936 00937 BOOST_CHECK( mslist->erase(Dummy(1,2,1)) == true ); 00938 BOOST_CHECK( mslist->erase(Dummy(1,2,6)) == true ); 00939 BOOST_CHECK( mslist->erase(Dummy(1,2,5)) == true ); 00940 BOOST_CHECK( mslist->erase(Dummy(1,2,2)) == true ); 00941 BOOST_CHECK( mslist->erase(Dummy(1,2,3)) == true ); 00942 00943 BOOST_CHECK( mslist->empty() ); 00944 } 00945 #endif 00946 00947 #ifdef OROPKG_OS_GNULINUX 00948 00949 BOOST_AUTO_TEST_SUITE_END() 00950 BOOST_FIXTURE_TEST_SUITE( BuffersStressLockFreeTestSuite, BuffersAQueueTest ) 00951 00952 BOOST_AUTO_TEST_CASE( testListLockFree ) 00953 { 00954 LLFWorker* aworker = new LLFWorker( listlockfree ); 00955 LLFWorker* bworker = new LLFWorker( listlockfree ); 00956 LLFWorker* cworker = new LLFWorker( listlockfree ); 00957 LLFGrower* grower = new LLFGrower( listlockfree ); 00958 00959 { 00960 boost::scoped_ptr<Activity> athread( new Activity(ORO_SCHED_OTHER, 0, 0, aworker, "ActivityA" )); 00961 boost::scoped_ptr<Activity> bthread( new Activity(ORO_SCHED_OTHER, 0, 0, bworker, "ActivityB" )); 00962 boost::scoped_ptr<Activity> cthread( new Activity(ORO_SCHED_OTHER, 0, 0, cworker, "ActivityC" )); 00963 boost::scoped_ptr<Activity> gthread( new Activity(ORO_SCHED_OTHER, 0, 0, grower, "ActivityG" )); 00964 00965 athread->start(); 00966 bthread->start(); 00967 cthread->start(); 00968 00969 sleep(5); 00970 gthread->start(); 00971 sleep(10); 00972 gthread->stop(); 00973 sleep(5); 00974 00975 athread->stop(); 00976 bthread->stop(); 00977 cthread->stop(); 00978 } 00979 00980 #if 0 00981 cout << "Athread appends: " << aworker->appends<<endl; 00982 cout << "Athread erases: " << aworker->erases<<endl; 00983 cout << "Bthread appends: " << bworker->appends<<endl; 00984 cout << "Bthread erases: " << bworker->erases<<endl; 00985 cout << "Cthread appends: " << cworker->appends<<endl; 00986 cout << "Cthread erases: " << cworker->erases<<endl; 00987 cout << "List capacity: "<< listlockfree->capacity()<<endl; 00988 cout << "List size: "<< listlockfree->size()<<endl; 00989 // while( listlockfree->empty() == false ) { 00990 // Dummy d = listlockfree->back(); 00991 // //cout << "Left: "<< d <<endl; 00992 // BOOST_CHECK( listlockfree->erase( d ) ); 00993 // } 00994 #endif 00995 00996 BOOST_CHECK( aworker->appends == aworker->erases ); 00997 BOOST_CHECK( bworker->appends == bworker->erases ); 00998 BOOST_CHECK( cworker->appends == cworker->erases ); 00999 01000 delete aworker; 01001 delete bworker; 01002 delete cworker; 01003 delete grower; 01004 } 01005 #endif 01006 01007 #ifdef OROPKG_OS_GNULINUX 01008 BOOST_AUTO_TEST_CASE( testAtomicQueue ) 01009 { 01010 QueueType* qt = new QueueType(QS); 01011 AQWorker<QueueType>* aworker = new AQWorker<QueueType>( qt ); 01012 AQWorker<QueueType>* bworker = new AQWorker<QueueType>( qt ); 01013 AQWorker<QueueType>* cworker = new AQWorker<QueueType>( qt ); 01014 AQGrower<QueueType>* grower = new AQGrower<QueueType>( qt ); 01015 AQEater<QueueType>* eater = new AQEater<QueueType>( qt ); 01016 01017 { 01018 boost::scoped_ptr<Activity> athread( new Activity(20, aworker, "ActivityA" )); 01019 boost::scoped_ptr<Activity> bthread( new Activity(20, bworker, "ActivityB" )); 01020 boost::scoped_ptr<Activity> cthread( new Activity(20, cworker, "ActivityC" )); 01021 boost::scoped_ptr<Activity> gthread( new Activity(20, grower, "ActivityG")); 01022 boost::scoped_ptr<Activity> ethread( new Activity(20, eater, "ActivityE")); 01023 01024 // avoid system lock-ups 01025 athread->thread()->setScheduler(ORO_SCHED_OTHER); 01026 bthread->thread()->setScheduler(ORO_SCHED_OTHER); 01027 cthread->thread()->setScheduler(ORO_SCHED_OTHER); 01028 gthread->thread()->setScheduler(ORO_SCHED_OTHER); 01029 01030 log(Info) <<"Stressing multi-read/multi-write..." <<endlog(); 01031 athread->start(); 01032 bthread->start(); 01033 cthread->start(); 01034 sleep(5); 01035 log(Info) <<"Stressing multi-read/multi-write...on full buffer" <<endlog(); 01036 gthread->start(); // stress full bufs 01037 sleep(5); 01038 gthread->stop(); 01039 log(Info) <<"Stressing multi-read/multi-write...on empty buffer" <<endlog(); 01040 ethread->start(); // stress empty bufs 01041 sleep(5); 01042 athread->stop(); 01043 bthread->stop(); 01044 cthread->stop(); 01045 gthread->start(); // stress single-reader single-writer 01046 log(Info) <<"Stressing read&write..." <<endlog(); 01047 sleep(5); 01048 gthread->stop(); 01049 ethread->stop(); 01050 } 01051 01052 cout <<endl 01053 << "Total appends: " << aworker->appends + bworker->appends + cworker->appends+ grower->appends<<endl; 01054 cout << "Total erases : " << aworker->erases + bworker->erases+ cworker->erases + qt->size() + eater->erases <<endl; 01055 if (aworker->appends + bworker->appends + cworker->appends+ grower->appends != aworker->erases + bworker->erases+ cworker->erases + int(qt->size()) + eater->erases) { 01056 cout << "Mismatch detected !" <<endl; 01057 } 01058 int i = 0; // left-over count 01059 Dummy* d = 0; 01060 BOOST_CHECK( qt->size() <= QS ); 01061 while( qt->size() != 0 ) { 01062 BOOST_CHECK( qt->dequeue(d) == true); 01063 BOOST_CHECK( d ); 01064 i++; 01065 if ( i > QS ) { 01066 BOOST_CHECK( i <= QS); // avoid infinite loop. 01067 break; 01068 } 01069 } 01070 cout << "Left in Queue: "<< i <<endl; 01071 BOOST_CHECK( qt->dequeue(d) == false ); 01072 BOOST_CHECK( qt->dequeue(d) == false ); 01073 BOOST_CHECK( qt->isEmpty() ); 01074 BOOST_CHECK_EQUAL( qt->size(), 0 ); 01075 01076 // assert: sum queues == sum dequeues 01077 BOOST_CHECK_EQUAL( aworker->appends + bworker->appends + cworker->appends + grower->appends, 01078 aworker->erases + bworker->erases + cworker->erases + i + eater->erases ); 01079 delete aworker; 01080 delete bworker; 01081 delete cworker; 01082 delete grower; 01083 delete eater; 01084 } 01085 01086 BOOST_AUTO_TEST_CASE( testAtomicMWSRQueue ) 01087 { 01088 MWSRQueueType* qt = new MWSRQueueType(QS); 01089 AQGrower<MWSRQueueType>* aworker = new AQGrower<MWSRQueueType>( qt ); 01090 AQGrower<MWSRQueueType>* bworker = new AQGrower<MWSRQueueType>( qt ); 01091 AQGrower<MWSRQueueType>* cworker = new AQGrower<MWSRQueueType>( qt ); 01092 AQGrower<MWSRQueueType>* grower = new AQGrower<MWSRQueueType>( qt ); 01093 AQEater<MWSRQueueType>* eater = new AQEater<MWSRQueueType>( qt ); 01094 01095 { 01096 boost::scoped_ptr<Activity> athread( new Activity(20, aworker, "ActivityA" )); 01097 boost::scoped_ptr<Activity> bthread( new Activity(20, bworker, "ActivityB" )); 01098 boost::scoped_ptr<Activity> cthread( new Activity(20, cworker, "ActivityC" )); 01099 boost::scoped_ptr<Activity> gthread( new Activity(20, grower, "ActivityG")); 01100 boost::scoped_ptr<Activity> ethread( new Activity(20, eater, "ActivityE")); 01101 01102 // avoid system lock-ups 01103 athread->thread()->setScheduler(ORO_SCHED_OTHER); 01104 bthread->thread()->setScheduler(ORO_SCHED_OTHER); 01105 cthread->thread()->setScheduler(ORO_SCHED_OTHER); 01106 gthread->thread()->setScheduler(ORO_SCHED_OTHER); 01107 ethread->thread()->setScheduler(ORO_SCHED_OTHER); 01108 01109 log(Info) <<"Stressing multi-write/single-read..." <<endlog(); 01110 athread->start(); 01111 bthread->start(); 01112 cthread->start(); 01113 gthread->start(); 01114 ethread->start(); 01115 sleep(5); 01116 athread->stop(); 01117 bthread->stop(); 01118 cthread->stop(); 01119 log(Info) <<"Stressing single-write/single-read..." <<endlog(); 01120 sleep(5); 01121 gthread->stop(); 01122 ethread->stop(); 01123 } 01124 01125 cout <<endl 01126 << "Total appends: " << aworker->appends + bworker->appends + cworker->appends+ grower->appends<<endl; 01127 cout << "Total erases : " << eater->erases <<endl; 01128 if (aworker->appends + bworker->appends + cworker->appends+ grower->appends != int(qt->size()) + eater->erases) { 01129 cout << "Mismatch detected !" <<endl; 01130 } 01131 int i = 0; // left-over count 01132 Dummy* d = 0; 01133 BOOST_CHECK( qt->size() <= QS ); 01134 while( qt->size() != 0 ) { 01135 BOOST_CHECK( qt->dequeue(d) == true); 01136 BOOST_CHECK( d ); 01137 i++; 01138 if ( i > QS ) { 01139 BOOST_CHECK( i <= QS); // avoid infinite loop. 01140 break; 01141 } 01142 } 01143 cout << "Left in Queue: "<< i <<endl; 01144 BOOST_CHECK( qt->dequeue(d) == false ); 01145 BOOST_CHECK( qt->dequeue(d) == false ); 01146 BOOST_CHECK( qt->isEmpty() ); 01147 BOOST_CHECK_EQUAL( qt->size(), 0 ); 01148 01149 // assert: sum queues == sum dequeues 01150 BOOST_CHECK_EQUAL( aworker->appends + bworker->appends + cworker->appends + grower->appends, 01151 i + eater->erases ); 01152 delete aworker; 01153 delete bworker; 01154 delete cworker; 01155 delete grower; 01156 delete eater; 01157 } 01158 #endif 01159 BOOST_AUTO_TEST_SUITE_END()