reSIProcate/stack  9694
testTypedef.cxx
Go to the documentation of this file.
00001 #include <cassert>
00002 #include <iostream>
00003 
00004 using namespace std;
00005 
00006 namespace resip
00007 {
00008 
00009 template <class P>
00010 class IntrusiveListElement
00011 {
00012    public:
00013       IntrusiveListElement() 
00014          : mNext(0),
00015            mPrev(0)
00016       {}
00017 
00018       virtual ~IntrusiveListElement() 
00019       {
00020          remove();
00021       }
00022 
00023       // make this element an empty list
00024       static P makeList(P elem)
00025       {
00026          assert(!elem->IntrusiveListElement::mNext);
00027 
00028          elem->IntrusiveListElement::mPrev = elem;
00029          elem->IntrusiveListElement::mNext = elem;
00030 
00031          return elem;
00032       }
00033 
00034       bool empty() const
00035       {
00036          assert(mPrev);
00037          assert(mNext);
00038 
00039          return mNext == static_cast<P>(const_cast<IntrusiveListElement<P>*>(this));
00040       }
00041 
00042       // .dlb. add reverse_iterator?
00043 
00044       class iterator
00045       {
00046          public:
00047             explicit iterator(const P start)
00048                : mPos(start)
00049             {}
00050 
00051             iterator& operator=(const iterator& rhs)
00052             {
00053                mPos = rhs.mPos;
00054                return *this;
00055             }
00056 
00057             iterator& operator++()
00058             {
00059                mPos = mPos->IntrusiveListElement::mNext;
00060                return *this;
00061             }
00062 
00063             bool operator==(const iterator& rhs)
00064             {
00065                return mPos == rhs.mPos;
00066             }
00067 
00068             bool operator!=(const iterator& rhs)
00069             {
00070                return mPos != rhs.mPos;
00071             }
00072 
00073             P operator*()
00074             {
00075                return mPos;
00076             }
00077 
00078          private:
00079             P mPos;
00080       };
00081 
00082       iterator begin()
00083       {
00084          assert(mPrev);
00085          assert(mNext);
00086          return iterator(mNext);
00087       }
00088 
00089       iterator end()
00090       {
00091          assert(mPrev);
00092          assert(mNext);
00093          return iterator(static_cast<P>(this));
00094       }
00095 
00096       friend class iterator;
00097 
00098       // pushing an element onto the same list twice is undefined
00099       void push_front(P elem)
00100       {
00101          assert(mPrev);
00102          assert(mNext);
00103 
00104          elem->IntrusiveListElement::mNext = mNext;
00105          elem->IntrusiveListElement::mPrev = static_cast<P>(this);
00106          
00107          elem->IntrusiveListElement::mNext->IntrusiveListElement::mPrev = elem;
00108          elem->IntrusiveListElement::mPrev->IntrusiveListElement::mNext = elem;
00109       }
00110 
00111       // putting an element onto the same list twice is undefined
00112       void push_back(P elem)
00113       {
00114          assert(mPrev);
00115          assert(mNext);
00116 
00117          elem->IntrusiveListElement::mPrev = mPrev;
00118          elem->IntrusiveListElement::mNext = static_cast<P>(this);
00119          
00120          elem->IntrusiveListElement::mPrev->IntrusiveListElement::mNext = elem;
00121          elem->IntrusiveListElement::mNext->IntrusiveListElement::mPrev = elem;
00122       }
00123 
00124       void remove()
00125       {
00126          if (mNext)
00127          {
00128             // prev  -> this -> next
00129             //       <-      <-
00130             //
00131             // prev -> next
00132             //      <-
00133             mNext->IntrusiveListElement::mPrev = mPrev;
00134             mPrev->IntrusiveListElement::mNext = mNext;
00135          }
00136 
00137          mNext = 0;
00138          mPrev = 0;
00139       }
00140 
00141    protected:
00142       mutable P mNext;
00143       mutable P mPrev;
00144 };
00145 
00146 template <class P>
00147 class IntrusiveListElement1
00148 {
00149    public:
00150       IntrusiveListElement1() 
00151          : mNext(0),
00152            mPrev(0)
00153       {}
00154 
00155       virtual ~IntrusiveListElement1() 
00156       {
00157          remove();
00158       }
00159 
00160       // make this element an empty list
00161       static P makeList(P elem)
00162       {
00163          assert(!elem->IntrusiveListElement1::mNext);
00164 
00165          elem->IntrusiveListElement1::mPrev = elem;
00166          elem->IntrusiveListElement1::mNext = elem;
00167 
00168          return elem;
00169       }
00170 
00171       bool empty() const
00172       {
00173          assert(mPrev);
00174          assert(mNext);
00175 
00176          return mNext == static_cast<P>(const_cast<IntrusiveListElement1<P>*>(this));
00177       }
00178 
00179       // .dlb. add reverse_iterator?
00180 
00181       class iterator
00182       {
00183          public:
00184             explicit iterator(const P start)
00185                : mPos(start)
00186             {}
00187 
00188             iterator& operator=(const iterator& rhs)
00189             {
00190                mPos = rhs.mPos;
00191                return *this;
00192             }
00193 
00194             iterator& operator++()
00195             {
00196                mPos = mPos->IntrusiveListElement1::mNext;
00197                return *this;
00198             }
00199 
00200             bool operator==(const iterator& rhs)
00201             {
00202                return mPos == rhs.mPos;
00203             }
00204 
00205             bool operator!=(const iterator& rhs)
00206             {
00207                return mPos != rhs.mPos;
00208             }
00209 
00210             P operator*()
00211             {
00212                return mPos;
00213             }
00214 
00215          private:
00216             P mPos;
00217       };
00218 
00219       iterator begin()
00220       {
00221          assert(mPrev);
00222          assert(mNext);
00223          return iterator(mNext);
00224       }
00225 
00226       iterator end()
00227       {
00228          assert(mPrev);
00229          assert(mNext);
00230          return iterator(static_cast<P>(this));
00231       }
00232 
00233       friend class iterator;
00234 
00235       // pushing an element onto the same list twice is undefined
00236       void push_front(P elem)
00237       {
00238          assert(mPrev);
00239          assert(mNext);
00240 
00241          elem->IntrusiveListElement1::mNext = mNext;
00242          elem->IntrusiveListElement1::mPrev = static_cast<P>(this);
00243          
00244          elem->IntrusiveListElement1::mNext->IntrusiveListElement1::mPrev = elem;
00245          elem->IntrusiveListElement1::mPrev->IntrusiveListElement1::mNext = elem;
00246       }
00247 
00248       // putting an element onto the same list twice is undefined
00249       void push_back(P elem)
00250       {
00251          assert(mPrev);
00252          assert(mNext);
00253 
00254          elem->IntrusiveListElement1::mPrev = mPrev;
00255          elem->IntrusiveListElement1::mNext = static_cast<P>(this);
00256          
00257          elem->IntrusiveListElement1::mPrev->IntrusiveListElement1::mNext = elem;
00258          elem->IntrusiveListElement1::mNext->IntrusiveListElement1::mPrev = elem;
00259       }
00260 
00261       void remove()
00262       {
00263          if (mNext)
00264          {
00265             // prev  -> this -> next
00266             //       <-      <-
00267             //
00268             // prev -> next
00269             //      <-
00270             mNext->IntrusiveListElement1::mPrev = mPrev;
00271             mPrev->IntrusiveListElement1::mNext = mNext;
00272          }
00273 
00274          mNext = 0;
00275          mPrev = 0;
00276       }
00277 
00278    protected:
00279       mutable P mNext;
00280       mutable P mPrev;
00281 };
00282 
00283 template <class P>
00284 class IntrusiveListElement2
00285 {
00286    public:
00287       IntrusiveListElement2() 
00288          : mNext(0),
00289            mPrev(0)
00290       {}
00291 
00292       virtual ~IntrusiveListElement2() 
00293       {
00294          remove();
00295       }
00296 
00297       // make this element an empty list
00298       static P makeList(P elem)
00299       {
00300          assert(!elem->IntrusiveListElement2::mNext);
00301 
00302          elem->IntrusiveListElement2::mPrev = elem;
00303          elem->IntrusiveListElement2::mNext = elem;
00304 
00305          return elem;
00306       }
00307 
00308       bool empty() const
00309       {
00310          assert(mPrev);
00311          assert(mNext);
00312 
00313          return mNext == static_cast<P>(const_cast<IntrusiveListElement2<P>*>(this));
00314       }
00315 
00316       // .dlb. add reverse_iterator?
00317 
00318       class iterator
00319       {
00320          public:
00321             explicit iterator(const P start)
00322                : mPos(start)
00323             {}
00324 
00325             iterator& operator=(const iterator& rhs)
00326             {
00327                mPos = rhs.mPos;
00328                return *this;
00329             }
00330 
00331             iterator& operator++()
00332             {
00333                mPos = mPos->IntrusiveListElement2::mNext;
00334                return *this;
00335             }
00336 
00337             bool operator==(const iterator& rhs)
00338             {
00339                return mPos == rhs.mPos;
00340             }
00341 
00342             bool operator!=(const iterator& rhs)
00343             {
00344                return mPos != rhs.mPos;
00345             }
00346 
00347             P operator*()
00348             {
00349                return mPos;
00350             }
00351 
00352          private:
00353             P mPos;
00354       };
00355 
00356       iterator begin()
00357       {
00358          assert(mPrev);
00359          assert(mNext);
00360          return iterator(mNext);
00361       }
00362 
00363       iterator end()
00364       {
00365          assert(mPrev);
00366          assert(mNext);
00367          return iterator(static_cast<P>(this));
00368       }
00369 
00370       friend class iterator;
00371 
00372       // pushing an element onto the same list twice is undefined
00373       void push_front(P elem)
00374       {
00375          assert(mPrev);
00376          assert(mNext);
00377 
00378          elem->IntrusiveListElement2::mNext = mNext;
00379          elem->IntrusiveListElement2::mPrev = static_cast<P>(this);
00380          
00381          elem->IntrusiveListElement2::mNext->IntrusiveListElement2::mPrev = elem;
00382          elem->IntrusiveListElement2::mPrev->IntrusiveListElement2::mNext = elem;
00383       }
00384 
00385       // putting an element onto the same list twice is undefined
00386       void push_back(P elem)
00387       {
00388          assert(mPrev);
00389          assert(mNext);
00390 
00391          elem->IntrusiveListElement2::mPrev = mPrev;
00392          elem->IntrusiveListElement2::mNext = static_cast<P>(this);
00393          
00394          elem->IntrusiveListElement2::mPrev->IntrusiveListElement2::mNext = elem;
00395          elem->IntrusiveListElement2::mNext->IntrusiveListElement2::mPrev = elem;
00396       }
00397 
00398       void remove()
00399       {
00400          if (mNext)
00401          {
00402             // prev  -> this -> next
00403             //       <-      <-
00404             //
00405             // prev -> next
00406             //      <-
00407             mNext->IntrusiveListElement2::mPrev = mPrev;
00408             mPrev->IntrusiveListElement2::mNext = mNext;
00409          }
00410 
00411          mNext = 0;
00412          mPrev = 0;
00413       }
00414 
00415    protected:
00416       mutable P mNext;
00417       mutable P mPrev;
00418 };
00419  
00420 } // end namespace resip
00421 
00422 using namespace resip;
00423 
00424 class Foo : public IntrusiveListElement<Foo*>
00425 {
00426    public:
00427       Foo(int v) : va1(v) {}
00428       int va1;
00429       int va2;
00430 };
00431 
00432 class FooFoo : public IntrusiveListElement<FooFoo*>, public IntrusiveListElement1<FooFoo*>
00433 {
00434    public:
00435       typedef IntrusiveListElement<FooFoo*> read;
00436       typedef IntrusiveListElement1<FooFoo*> write;
00437 
00438       FooFoo(int v) : va1(v) {}
00439 
00440       int va1;
00441       int va2;
00442 };
00443 
00444 int
00445 main(int argc, char* argv[])
00446 {
00447    {
00448       Foo* fooHead = new Foo(-1);
00449       Foo* foo1 = new Foo(1);
00450       Foo* foo2 = new Foo(2);
00451       Foo* foo3 = new Foo(3);
00452       Foo* foo4 = new Foo(4);
00453 
00454       Foo::makeList(fooHead);
00455       assert(fooHead->empty());
00456       for (Foo::iterator f = fooHead->begin(); f != fooHead->end(); ++f)
00457       {
00458          cerr << (*f)->va1 << endl;
00459       }
00460 
00461       fooHead->push_front(foo1);
00462       assert(!fooHead->empty());
00463       cerr << endl << "first" << endl;
00464       assert((*fooHead->begin())->va1 == 1);
00465       assert((*fooHead->end())->va1 == -1);
00466 
00467       Foo::iterator j = fooHead->begin();
00468       ++j;
00469       cerr << (*j)->va1 << endl;
00470       assert((*j)->va1 == -1);      
00471       assert(*j == *fooHead->end());
00472 
00473       for (Foo::iterator f = fooHead->begin(); f != fooHead->end(); ++f)
00474       {
00475          cerr << (*f)->va1 << endl;
00476       }
00477 
00478       fooHead->push_front(foo2);
00479       cerr << endl << "second" << endl;
00480       for (Foo::iterator f = fooHead->begin(); f != fooHead->end(); ++f)
00481       {
00482          cerr << (*f)->va1 << endl;
00483       }
00484 
00485       fooHead->push_front(foo3);   
00486       cerr << endl << "third" << endl;
00487       for (Foo::iterator f = fooHead->begin(); f != fooHead->end(); ++f)
00488       {
00489          cerr << (*f)->va1 << endl;
00490       }
00491 
00492       cerr << endl << "deleted second" << endl;
00493       delete foo2;
00494       for (Foo::iterator f = fooHead->begin(); f != fooHead->end(); ++f)
00495       {
00496          cerr << (*f)->va1 << endl;
00497       }
00498 
00499       cerr << endl << "fourth" << endl;
00500       fooHead->push_front(foo4);
00501       for (Foo::iterator f = fooHead->begin(); f != fooHead->end(); ++f)
00502       {
00503          cerr << (*f)->va1 << endl;
00504       }
00505 
00506       cerr << endl << "deleted fourth, first" << endl;
00507       delete foo1;
00508       delete foo4;
00509       for (Foo::iterator f = fooHead->begin(); f != fooHead->end(); ++f)
00510       {
00511          cerr << (*f)->va1 << endl;
00512       }
00513    
00514       cerr << endl << "deleted third (empty)" << endl;
00515       delete foo3;
00516       for (Foo::iterator f = fooHead->begin(); f != fooHead->end(); ++f)
00517       {
00518          cerr << (*f)->va1 << endl;
00519       }
00520    }
00521 
00522 // .abr. Yes, this really is necessary just to get things to compile. Don't ask
00523 // why -- it's clearly a compiler bug. But you would be well advised not to
00524 // comment it out unless you're actually using the SunPRO compiler, and have
00525 // found an alternate workaround.
00526 #if defined(__SUNPRO_CC)
00527    typedef IntrusiveListElement<FooFoo*> read;
00528    typedef IntrusiveListElement1<FooFoo*> write;
00529 #endif
00530 
00531    //=============================================================================
00532    // Read version
00533    //=============================================================================
00534    cerr << endl << "READ VERSION" << endl;
00535    {
00536       FooFoo* fooFooHead = new FooFoo(-1);
00537       FooFoo* fooFoo1 = new FooFoo(1);
00538       FooFoo* fooFoo2 = new FooFoo(2);
00539       FooFoo* fooFoo3 = new FooFoo(3);
00540       FooFoo* fooFoo4 = new FooFoo(4);
00541 
00542       FooFoo::read::makeList(fooFooHead);
00543       FooFoo::write::makeList(fooFooHead);
00544       assert(fooFooHead->read::empty());
00545       assert(fooFooHead->write::empty());
00546       for (FooFoo::read::iterator f = fooFooHead->read::begin(); f != fooFooHead->read::end(); ++f)
00547       {
00548          cerr << (*f)->va1 << endl;
00549       }
00550 
00551       fooFooHead->read::push_front(fooFoo1);
00552       assert(!fooFooHead->read::empty());
00553       assert(fooFooHead->write::empty());
00554       cerr << endl << "first" << endl;
00555       for (FooFoo::read::iterator f = fooFooHead->read::begin(); f != fooFooHead->read::end(); ++f)
00556       {
00557          cerr << (*f)->va1 << endl;
00558       }
00559 
00560       fooFooHead->read::push_front(fooFoo2);
00561       cerr << endl << "second" << endl;
00562       for (FooFoo::read::iterator f = fooFooHead->read::begin(); f != fooFooHead->read::end(); ++f)
00563       {
00564          cerr << (*f)->va1 << endl;
00565       }
00566 
00567       fooFooHead->read::push_front(fooFoo3);   
00568       cerr << endl << "third" << endl;
00569       for (FooFoo::read::iterator f = fooFooHead->read::begin(); f != fooFooHead->read::end(); ++f)
00570       {
00571          cerr << (*f)->va1 << endl;
00572       }
00573 
00574       cerr << endl << "deleted second" << endl;
00575       delete fooFoo2;
00576       for (FooFoo::read::iterator f = fooFooHead->read::begin(); f != fooFooHead->read::end(); ++f)
00577       {
00578          cerr << (*f)->va1 << endl;
00579       }
00580 
00581       cerr << endl << "fourth" << endl;
00582       fooFooHead->read::push_front(fooFoo4);
00583       for (FooFoo::read::iterator f = fooFooHead->read::begin(); f != fooFooHead->read::end(); ++f)
00584       {
00585          cerr << (*f)->va1 << endl;
00586       }
00587 
00588       cerr << endl << "deleted fourth, first" << endl;
00589       delete fooFoo1;
00590       delete fooFoo4;
00591       for (FooFoo::read::iterator f = fooFooHead->read::begin(); f != fooFooHead->read::end(); ++f)
00592       {
00593          cerr << (*f)->va1 << endl;
00594       }
00595    
00596       cerr << endl << "deleted third (empty)" << endl;
00597       delete fooFoo3;
00598       for (FooFoo::read::iterator f = fooFooHead->read::begin(); f != fooFooHead->read::end(); ++f)
00599       {
00600          cerr << (*f)->va1 << endl;
00601       }
00602    }
00603 
00604    //=============================================================================
00605    // Write version
00606    //=============================================================================
00607    cerr << endl << "WRITE VERSION" << endl;
00608    {      
00609       FooFoo* fooFooHead = new FooFoo(-1);
00610       FooFoo* fooFoo1 = new FooFoo(1);
00611       FooFoo* fooFoo2 = new FooFoo(2);
00612       FooFoo* fooFoo3 = new FooFoo(3);
00613       FooFoo* fooFoo4 = new FooFoo(4);
00614 
00615       FooFoo::write::makeList(fooFooHead);
00616       FooFoo::read::makeList(fooFooHead);
00617       assert(fooFooHead->write::empty());
00618       assert(fooFooHead->read::empty());
00619       for (FooFoo::write::iterator f = fooFooHead->write::begin(); f != fooFooHead->write::end(); ++f)
00620       {
00621          cerr << (*f)->va1 << endl;
00622       }
00623 
00624       fooFooHead->write::push_front(fooFoo1);
00625       assert(!fooFooHead->write::empty());
00626       assert(fooFooHead->read::empty());
00627       cerr << endl << "first" << endl;
00628       for (FooFoo::write::iterator f = fooFooHead->write::begin(); f != fooFooHead->write::end(); ++f)
00629       {
00630          cerr << (*f)->va1 << endl;
00631       }
00632 
00633       fooFooHead->write::push_front(fooFoo2);
00634       cerr << endl << "second" << endl;
00635       for (FooFoo::write::iterator f = fooFooHead->write::begin(); f != fooFooHead->write::end(); ++f)
00636       {
00637          cerr << (*f)->va1 << endl;
00638       }
00639 
00640       fooFooHead->write::push_front(fooFoo3);   
00641       cerr << endl << "third" << endl;
00642       for (FooFoo::write::iterator f = fooFooHead->write::begin(); f != fooFooHead->write::end(); ++f)
00643       {
00644          cerr << (*f)->va1 << endl;
00645       }
00646 
00647       cerr << endl << "deleted second" << endl;
00648       delete fooFoo2;
00649       for (FooFoo::write::iterator f = fooFooHead->write::begin(); f != fooFooHead->write::end(); ++f)
00650       {
00651          cerr << (*f)->va1 << endl;
00652       }
00653 
00654       cerr << endl << "fourth" << endl;
00655       fooFooHead->write::push_front(fooFoo4);
00656       for (FooFoo::write::iterator f = fooFooHead->write::begin(); f != fooFooHead->write::end(); ++f)
00657       {
00658          cerr << (*f)->va1 << endl;
00659       }
00660 
00661       cerr << endl << "deleted fourth, first" << endl;
00662       delete fooFoo1;
00663       delete fooFoo4;
00664       for (FooFoo::write::iterator f = fooFooHead->write::begin(); f != fooFooHead->write::end(); ++f)
00665       {
00666          cerr << (*f)->va1 << endl;
00667       }
00668    
00669       cerr << endl << "deleted third (empty)" << endl;
00670       delete fooFoo3;
00671       for (FooFoo::write::iterator f = fooFooHead->write::begin(); f != fooFooHead->write::end(); ++f)
00672       {
00673          cerr << (*f)->va1 << endl;
00674       }
00675    }
00676 
00677    return 0;
00678 }
00679 
00680 /* ====================================================================
00681  * The Vovida Software License, Version 1.0 
00682  * 
00683  * Copyright (c) 2000-2005 Vovida Networks, Inc.  All rights reserved.
00684  * 
00685  * Redistribution and use in source and binary forms, with or without
00686  * modification, are permitted provided that the following conditions
00687  * are met:
00688  * 
00689  * 1. Redistributions of source code must retain the above copyright
00690  *    notice, this list of conditions and the following disclaimer.
00691  * 
00692  * 2. Redistributions in binary form must reproduce the above copyright
00693  *    notice, this list of conditions and the following disclaimer in
00694  *    the documentation and/or other materials provided with the
00695  *    distribution.
00696  * 
00697  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00698  *    and "Vovida Open Communication Application Library (VOCAL)" must
00699  *    not be used to endorse or promote products derived from this
00700  *    software without prior written permission. For written
00701  *    permission, please contact vocal@vovida.org.
00702  *
00703  * 4. Products derived from this software may not be called "VOCAL", nor
00704  *    may "VOCAL" appear in their name, without prior written
00705  *    permission of Vovida Networks, Inc.
00706  * 
00707  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00708  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00709  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00710  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00711  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00712  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00713  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00714  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00715  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00716  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00717  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00718  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00719  * DAMAGE.
00720  * 
00721  * ====================================================================
00722  * 
00723  * This software consists of voluntary contributions made by Vovida
00724  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00725  * Inc.  For more information on Vovida Networks, Inc., please see
00726  * <http://www.vovida.org/>.
00727  *
00728  */