buffers_test.cpp
Go to the documentation of this file.
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()


rtt
Author(s): RTT Developers
autogenerated on Sat Jun 8 2019 18:46:06