00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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
00066
00067
00068
00069
00070
00071
00072
00073 };
00074
00075
00076 typedef AtomicQueue<Dummy*> QueueType;
00077 typedef AtomicMWSRQueue<Dummy*> MWSRQueueType;
00078
00079
00080
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
00147 lockfree = new BufferLockFree<Dummy>(QS);
00148 locked = new BufferLocked<Dummy>(QS);
00149 unsync = new BufferUnSync<Dummy>(QS);
00150
00151
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
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
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
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 ) );
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
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
00530 while ( mlst->append( Dummy(i,i,i) ) ) { ++i; ++appends; }
00531
00532 while ( mlst->erase( Dummy(i-1,i-1,i-1) ) ) { --i; ++erases; }
00533 }
00534
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
00558 while (stop == false && i < 2500 ) {
00559
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
00599 if ( mlst->enqueue( d ) ) { ++appends; }
00600
00601 if ( mlst->dequeue( d ) ) {
00602 if( *d != *orig) {
00603 os::MutexLock lock(m);
00604 assert(*d == *orig);
00605 }
00606 ++erases;
00607 }
00608 }
00609
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
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
00679 Dummy* d;
00680 while (stop == false ) {
00681 if ( mlst->dequeue(d) ) {
00682
00683
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 );
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 );
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
00838 TsPool<Dummy>::size_type sz = QS;
00839
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
00846 for (TsPool<Dummy>::size_type i = 0; i <3*sz; ++i ) {
00847
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
00859 std::vector<Dummy*> mpv;
00860
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
00884 mslist->reserve(7);
00885 BOOST_CHECK( mslist->empty() );
00886
00887
00888 BOOST_CHECK( mslist->hasKey(Dummy()) == false );
00889
00890
00891 BOOST_CHECK( mslist->erase(Dummy()) == false );
00892
00893
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
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
00990
00991
00992
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
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();
01037 sleep(5);
01038 gthread->stop();
01039 log(Info) <<"Stressing multi-read/multi-write...on empty buffer" <<endlog();
01040 ethread->start();
01041 sleep(5);
01042 athread->stop();
01043 bthread->stop();
01044 cthread->stop();
01045 gthread->start();
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;
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);
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
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
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;
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);
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
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()