|
reSIProcate/stack
9694
|
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 */
1.7.5.1