|
reSIProcate/rutil
9694
|
00001 #ifndef RESIP_IntrusiveListElement 00002 #define RESIP_IntrusiveListElement 00003 00057 namespace resip 00058 { 00059 00060 template <class P> 00061 class IntrusiveListElement 00062 { 00063 public: 00064 IntrusiveListElement() 00065 : mNext(0), 00066 mPrev(0) 00067 {} 00068 00069 virtual ~IntrusiveListElement() 00070 { 00071 remove(); 00072 } 00073 00074 // make this element an empty list 00075 static P makeList(P elem) 00076 { 00077 assert(!elem->IntrusiveListElement<P>::mNext); 00078 00079 elem->IntrusiveListElement<P>::mPrev = elem; 00080 elem->IntrusiveListElement<P>::mNext = elem; 00081 00082 return elem; 00083 } 00084 00085 bool empty() const 00086 { 00087 assert(mPrev); 00088 assert(mNext); 00089 00090 return static_cast<const IntrusiveListElement<P>*>(mNext) == static_cast<const IntrusiveListElement<P>*>(this); 00091 } 00092 00093 // .dlb. add reverse_iterator? 00094 00095 class iterator 00096 { 00097 public: 00098 explicit iterator(const P start) 00099 : mPos(start) 00100 {} 00101 00102 iterator& operator=(const iterator& rhs) 00103 { 00104 mPos = rhs.mPos; 00105 return *this; 00106 } 00107 00108 iterator& operator++() 00109 { 00110 mPos = mPos->IntrusiveListElement<P>::mNext; 00111 return *this; 00112 } 00113 00114 bool operator==(const iterator& rhs) 00115 { 00116 return mPos == rhs.mPos; 00117 } 00118 00119 bool operator!=(const iterator& rhs) 00120 { 00121 return mPos != rhs.mPos; 00122 } 00123 00124 P operator*() 00125 { 00126 return mPos; 00127 } 00128 00129 private: 00130 P mPos; 00131 }; 00132 00133 iterator begin() 00134 { 00135 assert(mPrev); 00136 assert(mNext); 00137 return iterator(mNext); 00138 } 00139 00140 iterator end() 00141 { 00142 assert(mPrev); 00143 assert(mNext); 00144 return iterator(static_cast<P>(this)); 00145 } 00146 00147 friend class iterator; 00148 00149 // pushing an element onto the same list twice is undefined 00150 void push_front(P elem) 00151 { 00152 assert(mPrev); 00153 assert(mNext); 00154 00155 elem->IntrusiveListElement<P>::mNext = mNext; 00156 elem->IntrusiveListElement<P>::mPrev = static_cast<P>(this); 00157 00158 elem->IntrusiveListElement<P>::mNext->IntrusiveListElement<P>::mPrev = elem; 00159 elem->IntrusiveListElement<P>::mPrev->IntrusiveListElement<P>::mNext = elem; 00160 } 00161 00162 // putting an element onto the same list twice is undefined 00163 void push_back(P elem) 00164 { 00165 assert(mPrev); 00166 assert(mNext); 00167 00168 elem->IntrusiveListElement<P>::mPrev = mPrev; 00169 elem->IntrusiveListElement<P>::mNext = static_cast<P>(this); 00170 00171 elem->IntrusiveListElement<P>::mPrev->IntrusiveListElement<P>::mNext = elem; 00172 elem->IntrusiveListElement<P>::mNext->IntrusiveListElement<P>::mPrev = elem; 00173 } 00174 00175 void remove() 00176 { 00177 if (mNext) 00178 { 00179 // prev -> this -> next 00180 // <- <- 00181 // 00182 // prev -> next 00183 // <- 00184 mNext->IntrusiveListElement<P>::mPrev = mPrev; 00185 mPrev->IntrusiveListElement<P>::mNext = mNext; 00186 } 00187 00188 mNext = 0; 00189 mPrev = 0; 00190 } 00191 00192 protected: 00193 mutable P mNext; 00194 mutable P mPrev; 00195 }; 00196 00197 template <class P> 00198 class IntrusiveListElement1 00199 { 00200 public: 00201 IntrusiveListElement1() 00202 : mNext(0), 00203 mPrev(0) 00204 {} 00205 00206 virtual ~IntrusiveListElement1() 00207 { 00208 remove(); 00209 } 00210 00211 // make this element an empty list 00212 static P makeList(P elem) 00213 { 00214 assert(!elem->IntrusiveListElement1<P>::mNext); 00215 00216 elem->IntrusiveListElement1<P>::mPrev = elem; 00217 elem->IntrusiveListElement1<P>::mNext = elem; 00218 00219 return elem; 00220 } 00221 00222 bool empty() const 00223 { 00224 assert(mPrev); 00225 assert(mNext); 00226 00227 return static_cast<const IntrusiveListElement1<P>*>(mNext) == static_cast<const IntrusiveListElement1<P>*>(this); 00228 } 00229 00230 // .dlb. add reverse_iterator? 00231 00232 class iterator 00233 { 00234 public: 00235 explicit iterator(const P start) 00236 : mPos(start) 00237 {} 00238 00239 iterator& operator=(const iterator& rhs) 00240 { 00241 mPos = rhs.mPos; 00242 return *this; 00243 } 00244 00245 iterator& operator++() 00246 { 00247 mPos = mPos->IntrusiveListElement1<P>::mNext; 00248 return *this; 00249 } 00250 00251 bool operator==(const iterator& rhs) 00252 { 00253 return mPos == rhs.mPos; 00254 } 00255 00256 bool operator!=(const iterator& rhs) 00257 { 00258 return mPos != rhs.mPos; 00259 } 00260 00261 P operator*() 00262 { 00263 return mPos; 00264 } 00265 00266 private: 00267 P mPos; 00268 }; 00269 00270 iterator begin() 00271 { 00272 assert(mPrev); 00273 assert(mNext); 00274 return iterator(mNext); 00275 } 00276 00277 iterator end() 00278 { 00279 assert(mPrev); 00280 assert(mNext); 00281 return iterator(static_cast<P>(this)); 00282 } 00283 00284 friend class iterator; 00285 00286 // pushing an element onto the same list twice is undefined 00287 void push_front(P elem) 00288 { 00289 assert(mPrev); 00290 assert(mNext); 00291 00292 elem->IntrusiveListElement1<P>::mNext = mNext; 00293 elem->IntrusiveListElement1<P>::mPrev = static_cast<P>(this); 00294 00295 elem->IntrusiveListElement1<P>::mNext->IntrusiveListElement1<P>::mPrev = elem; 00296 elem->IntrusiveListElement1<P>::mPrev->IntrusiveListElement1<P>::mNext = elem; 00297 } 00298 00299 // putting an element onto the same list twice is undefined 00300 void push_back(P elem) 00301 { 00302 assert(mPrev); 00303 assert(mNext); 00304 00305 elem->IntrusiveListElement1<P>::mPrev = mPrev; 00306 elem->IntrusiveListElement1<P>::mNext = static_cast<P>(this); 00307 00308 elem->IntrusiveListElement1<P>::mPrev->IntrusiveListElement1<P>::mNext = elem; 00309 elem->IntrusiveListElement1<P>::mNext->IntrusiveListElement1<P>::mPrev = elem; 00310 } 00311 00312 void remove() 00313 { 00314 if (mNext) 00315 { 00316 // prev -> this -> next 00317 // <- <- 00318 // 00319 // prev -> next 00320 // <- 00321 mNext->IntrusiveListElement1<P>::mPrev = mPrev; 00322 mPrev->IntrusiveListElement1<P>::mNext = mNext; 00323 } 00324 00325 mNext = 0; 00326 mPrev = 0; 00327 } 00328 00329 protected: 00330 mutable P mNext; 00331 mutable P mPrev; 00332 }; 00333 00334 template <class P> 00335 class IntrusiveListElement2 00336 { 00337 public: 00338 IntrusiveListElement2() 00339 : mNext(0), 00340 mPrev(0) 00341 {} 00342 00343 virtual ~IntrusiveListElement2() 00344 { 00345 remove(); 00346 } 00347 00348 // make this element an empty list 00349 static P makeList(P elem) 00350 { 00351 assert(!elem->IntrusiveListElement2<P>::mNext); 00352 00353 elem->IntrusiveListElement2<P>::mPrev = elem; 00354 elem->IntrusiveListElement2<P>::mNext = elem; 00355 00356 return elem; 00357 } 00358 00359 bool empty() const 00360 { 00361 assert(mPrev); 00362 assert(mNext); 00363 00364 return static_cast<const IntrusiveListElement2<P>*>(mNext) == static_cast<const IntrusiveListElement2<P>*>(this); 00365 } 00366 00367 // .dlb. add reverse_iterator? 00368 00369 class iterator 00370 { 00371 public: 00372 explicit iterator(const P start) 00373 : mPos(start) 00374 {} 00375 00376 iterator& operator=(const iterator& rhs) 00377 { 00378 mPos = rhs.mPos; 00379 return *this; 00380 } 00381 00382 iterator& operator++() 00383 { 00384 mPos = mPos->IntrusiveListElement2<P>::mNext; 00385 return *this; 00386 } 00387 00388 bool operator==(const iterator& rhs) 00389 { 00390 return mPos == rhs.mPos; 00391 } 00392 00393 bool operator!=(const iterator& rhs) 00394 { 00395 return mPos != rhs.mPos; 00396 } 00397 00398 P operator*() 00399 { 00400 return mPos; 00401 } 00402 00403 private: 00404 P mPos; 00405 }; 00406 00407 iterator begin() 00408 { 00409 assert(mPrev); 00410 assert(mNext); 00411 return iterator(mNext); 00412 } 00413 00414 iterator end() 00415 { 00416 assert(mPrev); 00417 assert(mNext); 00418 return iterator(static_cast<P>(this)); 00419 } 00420 00421 friend class iterator; 00422 00423 // pushing an element onto the same list twice is undefined 00424 void push_front(P elem) 00425 { 00426 assert(mPrev); 00427 assert(mNext); 00428 00429 elem->IntrusiveListElement2<P>::mNext = mNext; 00430 elem->IntrusiveListElement2<P>::mPrev = static_cast<P>(this); 00431 00432 elem->IntrusiveListElement2<P>::mNext->IntrusiveListElement2<P>::mPrev = elem; 00433 elem->IntrusiveListElement2<P>::mPrev->IntrusiveListElement2<P>::mNext = elem; 00434 } 00435 00436 // putting an element onto the same list twice is undefined 00437 void push_back(P elem) 00438 { 00439 assert(mPrev); 00440 assert(mNext); 00441 00442 elem->IntrusiveListElement2<P>::mPrev = mPrev; 00443 elem->IntrusiveListElement2<P>::mNext = static_cast<P>(this); 00444 00445 elem->IntrusiveListElement2<P>::mPrev->IntrusiveListElement2<P>::mNext = elem; 00446 elem->IntrusiveListElement2<P>::mNext->IntrusiveListElement2<P>::mPrev = elem; 00447 } 00448 00449 void remove() 00450 { 00451 if (mNext) 00452 { 00453 // prev -> this -> next 00454 // <- <- 00455 // 00456 // prev -> next 00457 // <- 00458 mNext->IntrusiveListElement2<P>::mPrev = mPrev; 00459 mPrev->IntrusiveListElement2<P>::mNext = mNext; 00460 } 00461 00462 mNext = 0; 00463 mPrev = 0; 00464 } 00465 00466 protected: 00467 mutable P mNext; 00468 mutable P mPrev; 00469 }; 00470 00471 template <class P> 00472 class IntrusiveListElement3 00473 { 00474 public: 00475 IntrusiveListElement3() 00476 : mNext(0), 00477 mPrev(0) 00478 {} 00479 00480 virtual ~IntrusiveListElement3() 00481 { 00482 remove(); 00483 } 00484 00485 // make this element an empty list 00486 static P makeList(P elem) 00487 { 00488 assert(!elem->IntrusiveListElement3<P>::mNext); 00489 00490 elem->IntrusiveListElement3<P>::mPrev = elem; 00491 elem->IntrusiveListElement3<P>::mNext = elem; 00492 00493 return elem; 00494 } 00495 00496 bool empty() const 00497 { 00498 assert(mPrev); 00499 assert(mNext); 00500 00501 return static_cast<const IntrusiveListElement3<P>*>(mNext) == static_cast<const IntrusiveListElement3<P>*>(this); 00502 } 00503 00504 // .dlb. add reverse_iterator? 00505 00506 class iterator 00507 { 00508 public: 00509 explicit iterator(const P start) 00510 : mPos(start) 00511 {} 00512 00513 iterator& operator=(const iterator& rhs) 00514 { 00515 mPos = rhs.mPos; 00516 return *this; 00517 } 00518 00519 iterator& operator++() 00520 { 00521 mPos = mPos->IntrusiveListElement3<P>::mNext; 00522 return *this; 00523 } 00524 00525 bool operator==(const iterator& rhs) 00526 { 00527 return mPos == rhs.mPos; 00528 } 00529 00530 bool operator!=(const iterator& rhs) 00531 { 00532 return mPos != rhs.mPos; 00533 } 00534 00535 P operator*() 00536 { 00537 return mPos; 00538 } 00539 00540 private: 00541 P mPos; 00542 }; 00543 00544 iterator begin() 00545 { 00546 assert(mPrev); 00547 assert(mNext); 00548 return iterator(mNext); 00549 } 00550 00551 iterator end() 00552 { 00553 assert(mPrev); 00554 assert(mNext); 00555 return iterator(static_cast<P>(this)); 00556 } 00557 00558 friend class iterator; 00559 00560 // pushing an element onto the same list twice is undefined 00561 void push_front(P elem) 00562 { 00563 assert(mPrev); 00564 assert(mNext); 00565 00566 elem->IntrusiveListElement3<P>::mNext = mNext; 00567 elem->IntrusiveListElement3<P>::mPrev = static_cast<P>(this); 00568 00569 elem->IntrusiveListElement3<P>::mNext->IntrusiveListElement3<P>::mPrev = elem; 00570 elem->IntrusiveListElement3<P>::mPrev->IntrusiveListElement3<P>::mNext = elem; 00571 } 00572 00573 // putting an element onto the same list twice is undefined 00574 void push_back(P elem) 00575 { 00576 assert(mPrev); 00577 assert(mNext); 00578 00579 elem->IntrusiveListElement3<P>::mPrev = mPrev; 00580 elem->IntrusiveListElement3<P>::mNext = static_cast<P>(this); 00581 00582 elem->IntrusiveListElement3<P>::mPrev->IntrusiveListElement3<P>::mNext = elem; 00583 elem->IntrusiveListElement3<P>::mNext->IntrusiveListElement3<P>::mPrev = elem; 00584 } 00585 00586 void remove() 00587 { 00588 if (mNext) 00589 { 00590 // prev -> this -> next 00591 // <- <- 00592 // 00593 // prev -> next 00594 // <- 00595 mNext->IntrusiveListElement3<P>::mPrev = mPrev; 00596 mPrev->IntrusiveListElement3<P>::mNext = mNext; 00597 } 00598 00599 mNext = 0; 00600 mPrev = 0; 00601 } 00602 00603 protected: 00604 mutable P mNext; 00605 mutable P mPrev; 00606 }; 00607 00608 } 00609 00610 #endif 00611 00612 00613 /* ==================================================================== 00614 * The Vovida Software License, Version 1.0 00615 * 00616 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00617 * 00618 * Redistribution and use in source and binary forms, with or without 00619 * modification, are permitted provided that the following conditions 00620 * are met: 00621 * 00622 * 1. Redistributions of source code must retain the above copyright 00623 * notice, this list of conditions and the following disclaimer. 00624 * 00625 * 2. Redistributions in binary form must reproduce the above copyright 00626 * notice, this list of conditions and the following disclaimer in 00627 * the documentation and/or other materials provided with the 00628 * distribution. 00629 * 00630 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00631 * and "Vovida Open Communication Application Library (VOCAL)" must 00632 * not be used to endorse or promote products derived from this 00633 * software without prior written permission. For written 00634 * permission, please contact vocal@vovida.org. 00635 * 00636 * 4. Products derived from this software may not be called "VOCAL", nor 00637 * may "VOCAL" appear in their name, without prior written 00638 * permission of Vovida Networks, Inc. 00639 * 00640 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00641 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00642 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00643 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00644 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00645 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00646 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00647 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00648 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00649 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00650 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00651 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00652 * DAMAGE. 00653 * 00654 * ==================================================================== 00655 * 00656 * This software consists of voluntary contributions made by Vovida 00657 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00658 * Inc. For more information on Vovida Networks, Inc., please see 00659 * <http://www.vovida.org/>. 00660 * 00661 */
1.7.5.1