lkptr
|
00001 /* lkptr.h (C) 2007 adolfo@di-mare.com */ 00002 00003 /* THIS IS FREE SOFWTWARE. 00004 - Use at your own risk; acknowledge authorship, please. 00005 - You can never blame the author for your use of this software. 00006 - Released to the world under LGPLv3: 00007 http://www.gnu.org/licenses/lgpl-3.0.html 00008 */ 00009 00010 /** \file lkptr.h 00011 \brief simple reference LinKed PoinTeR. 00012 \see http://www.di-mare.com/adolfo/p/lkptr.htm 00013 00014 \author Adolfo Di Mare <adolfo@di-mare.com> 00015 \date 2007 00016 */ 00017 00018 /** \class lkptr. 00019 \brief These smart pointer share the object they point to. 00020 Only after the last pointer releases its reference will the object be deleted. 00021 - Whenever the object will be changed by one of the pointers, all the 00022 other pointers will also see the change. 00023 - The implementation stores three pointers for every \c lkptr, 00024 but does not allocate anything on the free store. 00025 - Every \c lkptr is implemented using 3 internal pointers which 00026 makes it 3 times as big as a regular pointer. In exchange, 00027 automatic garbage collection is provided by the C++ 00028 constructor - destructor protocol of execution. 00029 - These pointers are double linked together. When only one pointer 00030 is in the chain, then the object will be deleted if the pointer 00031 releases it. Otherwise, the object will not be deleted because 00032 the other pointers in the chain are still referencing it. 00033 - These pointers are not intrusive, because they do not need an 00034 extra field in the pointed object to keep track of how many 00035 pointers reference the same object. 00036 - These pointers do not allocate extra memory to keep track of the 00037 reference count, because the linked list itself binds together 00038 all pointers that reference the same object. 00039 - A diagram for the pointer chain is shown in the documentation for 00040 method \c ok(). 00041 - Many of the pointer operators will never throw exceptions (hence 00042 the \c "throw()" especification in the method signature). 00043 - Memory leaks are extremely rare. Reference counting/linking can 00044 leak in the case of circular references (i.e., when the pointed 00045 object itself contains a counted/linked pointer, which points 00046 to an object that contains the original counted/linked pointer). 00047 - These pointers cannot be used in ROM memory because they modify 00048 each other when double linking, even if they are \c const. 00049 00050 \par Usage: 00051 \code 00052 void foo() { 00053 lkptr<AnyClass> p(new AnyClass); // "p" is one smart-pointer 00054 lkptr<AnyClass> q; // "q" is the other smart-pointer 00055 00056 p->DoSomething(); // no syntax change when using pointers 00057 q = p; // share the object 00058 q->Change(); // both "*p" && "*q" get changed 00059 p = q; // both still point to the same object 00060 lkptr<AnyClass> r = p; // The 3 of them share the same object 00061 00062 // delete p; // No need to worry about destruction 00063 // delete q; // the lkptr<> destructor will handle deletions for you. 00064 // delete r; 00065 } 00066 \endcode 00067 00068 - This work is based on Sharon's paper: 00069 - "Smart Pointers - What, Why, Which?" 00070 - http://ootips.org/yonat/4dev/smart-pointers.html 00071 - Yonat Sharon <yonat@ootips.org> 00072 - 1999. 00073 */ 00074 template <typename X> 00075 class lkptr; 00076 00077 /** \class array_lkptr. 00078 \brief Similar to \c lkptr<>, but points to an array instead of a single object. 00079 */ 00080 template <typename X> 00081 class array_lkptr; 00082 00083 /// MOD this when your compiler does compile this correctly. 00084 #undef COMPILER_lkptr 00085 00086 #ifdef _MSC_VER 00087 #if _MSC_VER >= 1300 // .net Microsoft Visual Studio C++ 00088 #define COMPILER_lkptr 00089 #endif 00090 #endif 00091 00092 #ifdef __BORLANDC__ // Borland C++ 00093 #if (__BORLANDC__ <= 0x0410) // BC++ v3.1 or earlier 00094 #undef COMPILER_lkptr 00095 #endif 00096 #endif 00097 00098 #ifdef __GNUC__ // GNU C++ 00099 #define COMPILER_lkptr 00100 #endif 00101 00102 #ifndef COMPILER_lkptr 00103 #error Compiler not yet supported // emit error 00104 #define lkptr_h // avoid file inclussion || compilation 00105 #endif 00106 00107 #ifndef lkptr_h 00108 #define lkptr_h ///< Avoid multiple file inclusion 00109 00110 #if 0 00111 +-----------+ *X 00112 | lkptr_rep | *next 00113 +-----------+ *prev 00114 | 00115 +----------------+ 00116 | | 00117 +-----------+ +-----------+ 00118 |array_lkptr| | lkptr | 00119 +-----------+ +-----------+ 00120 | 00121 +----------------+ 00122 | | 00123 +-----------+ +-----------+ 00124 | wide_lkptr| | weak_lkptr| 00125 *my_weak |-----------| |-----------| *owner 00126 +-----------+ +-----------+ 00127 00128 - lkptr_rep: Contains the 3 pointers [*X *next *prev] 00129 - lktpr: Contains the 3 pointers [*X *next *prev] 00130 - array_lkptr: Contains the 3 pointers [*X *next *prev] 00131 00132 - wide_lkptr: this->my_weak points to my weak_lkptr<> chain 00133 - weak_lkptr: this->owner point to the wide_lkptr<> where iAmGlued 00134 - weak_lkptr: Only one weak_lkptr<> in chain has (this->owner!=0) 00135 - wide_lkptr: More than one lkptr<> in chain can have its weak_lkptr<> chain 00136 - array_weak_lkptr: not supported 00137 #endif 00138 00139 #if 0 00140 lkptr chain weak_lkptr chain 00141 /---\ 00142 +---+ +---+ my_weak /------->| | 00143 | |<------->| |--->--\ | \---/ 00144 +---+ +---+ \ v ^ 00145 ^ ^ \ /---\ | 00146 | | \--<---| | | 00147 | | owner \---/ | 00148 v v ^ v 00149 +---+ +---+ | /---\ 00150 | |<------->| | \------->| | 00151 +---+ +---+ \---/ 00152 #endif 00153 00154 /* 00155 Neither weak_lkptr<> nor wide_lkptr<> have been implemented. 00156 - If you need them, use boost::weak_ptr<>'s with boost::shared_ptr<>'s. 00157 - They DO need an external reference count, allocated in heap memory 00158 but this reference count can be obtained when the intelligent pointer 00159 is created invoking one of these factory functions: 00160 - make_shared(). 00161 - allocate_shared(). 00162 - These boost pointers have good multi-threadh capabilities. 00163 - http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/smart_ptr.htm 00164 - http://www.google.com/search?num=100&q=site:boost.com+smart_ptr.htm 00165 */ 00166 00167 /// Accesory class that contains the fields all \c lkptr<> intelligent pointers. 00168 template <typename X> 00169 class base_lkptr { // not an inheritance base for lkptr<>'s 00170 template <typename Y> friend class lkptr; // contains 3 pointers 00171 template <typename Y> friend class array_lkptr; // contains 3 pointers 00172 template <typename Y> friend class wide_lkptr; // contains 4 pointers 00173 template <typename Y> friend class weak_lkptr; // contains 4 pointers 00174 template <typename Y> friend class test_lkptr; 00175 00176 private: // Rep 00177 X * ptr; ///< Pointer to referenced object (can be a \c NULL pointer). 00178 base_lkptr * prev; ///< Next in pointer chain. 00179 base_lkptr * next; ///< Previous in pointer chain. 00180 00181 public: // Nothing is public in a base_lkptr<>: 00182 private: // - Only the other lkptr<> classes can use it. 00183 00184 /// Default constructor and constructor from a regular pointer. 00185 explicit base_lkptr(X* p = 0) throw() : ptr(p) { prev = next = this; } 00186 00187 /// Constructor from a pointer to a derived class. 00188 /// - Check that the pointer is not null when types are not compatible. 00189 /// - Make sure the destructor for the base class is virtual. 00190 template <typename Y> 00191 explicit base_lkptr( Y* p ) throw() : ptr( dynamic_cast<X*>(p) ) 00192 { prev = next = this; } 00193 00194 /// Copy constructor: share the object with other pointers. 00195 base_lkptr( const base_lkptr& r ) throw() 00196 { acquire( const_cast<base_lkptr*>( &r ) ); } 00197 00198 /// Copy constructor from a derived clase: share the object with other pointers. 00199 /// - Check that the pointer is not null when types are not compatible. 00200 /// - Make sure the destructor for the base class is virtual. 00201 template <typename Y> 00202 explicit base_lkptr( const base_lkptr<Y>& r ) throw() { 00203 ptr = dynamic_cast<X*>( r.get() ); // ( r.ptr ) 00204 if ( 0==ptr ) { autolink(); } // invalid cast 00205 else { 00206 acquire( 00207 const_cast<base_lkptr*>( // remove "const" 00208 reinterpret_cast<const base_lkptr*>( &r ) ) ); // convert to pointer 00209 } 00210 } 00211 00212 /// Destructor. Delete only if last reference. 00213 /// - The derived \c lkptr<>'s do the destruction. 00214 ~base_lkptr() { } 00215 00216 /// Makes \c this->ptr point to \c r.ptr. 00217 /// - Insert \c "this" after \c "r" in the double chained pointer list. 00218 /// - If called after \c fast_release() will restore the invariant into \c "this". 00219 /// - Will link (this <--> r) even when r->ptr is a \c NULL pointer. 00220 void acquire(base_lkptr* r) throw() { 00221 this->ptr = r->ptr; // reference r's object 00222 this->next = r->next; 00223 this->next->prev = this; // 4 assignments to change the 4 next+prev chain pointers 00224 this->prev = r; 00225 r->next = this; 00226 // To double link with the list, "*r" must be changed. But the whole 00227 // implementation is easier if "*r" is const. 00228 } 00229 00230 /// Unlink from pointer chain. 00231 void unlink() { 00232 prev->next = next; 00233 next->prev = prev; 00234 } 00235 /// Autolink: \c unique() becomes \c true. 00236 void autolink() { 00237 prev = next = this; 00238 } 00239 00240 #ifdef lkptr_MERGE_IS_PUBLIC 00241 /// Releases the object. 00242 /// - Should never be needed: use \c wide_lkptr<> && \c weak_lkptr<>. 00243 /// - Before: If this was the last reference, it will not delete the referenced object. 00244 /// - After: The pointer becomes \c NULL. 00245 /// - After: Simliar to \c reset(0) (with no delete). 00246 /// - Difference: never deletes the pointed object. 00247 void weak_release() { 00248 unlink(); // unlink from pointer chain 00249 autolink(); // restore invariant: unique in chain 00250 ptr = 0; 00251 } 00252 00253 /// Releases the object. 00254 /// - If \c this->ptr is the last reference, it also deletes the object. 00255 /// - Leaves all the fields in \c "this" in a broken state. 00256 /// - Caller must ensure that all the fields get good values after invocation. 00257 void fast_release() { 00258 if ( prev == this ) { // auto-linked ==> unique() 00259 if ( ptr!=0 ) { 00260 delete ptr; // this could throw an exception 00261 } 00262 } 00263 else { // ! unique() ==> unlink from pointer chain 00264 unlink(); 00265 } 00266 // leaves all the fields in a broken state: 00267 // prev = next = this; // set-all to nil pointer 00268 // ptr = 0; 00269 } 00270 #endif 00271 00272 #ifdef lkptr_MERGE_IS_PUBLIC 00273 public: void merge( base_lkptr& r ); 00274 #else 00275 private: void merge( base_lkptr& r ); public: 00276 #endif 00277 00278 // Pointer access operators (these never throw exceptions) 00279 X* get() const throw() { return ptr; } ///< Returns a pointer to referenced object. 00280 X& value() const throw() { return *ptr; } ///< Returns the referenced object. 00281 X& operator*() const throw() { return *ptr; } ///< Returns the referenced object. 00282 X* operator->() const throw() { return ptr; } ///< Returns a pointer to referenced object. 00283 // operator X* () const throw() { return ptr; } ///< Returns a pointer to referenced object. 00284 00285 /// Returns \c true if the object pointed is null and \c false otherwise. 00286 bool isNull() const throw() { return ptr == 0; } 00287 00288 /// Return \c "true" when only one pointer references the object. 00289 bool unique() const throw() { return ( prev == this ); } 00290 00291 /// Returns how many pointers are sharing the object referenced by \c "this". 00292 /// \dontinclude test_lkptr.cpp \skipline test::null_3x1 00293 /// \until }} 00294 int use_count() const throw(); 00295 00296 bool ok() const throw(); 00297 template <typename Y> friend bool check_ok( const base_lkptr<Y>& p ) throw(); 00298 00299 }; // base_lkptr 00300 00301 /// Blends together \c *this and \c r when both point to the same object. 00302 /// - Should never be needed because it is erroneous to have unrelated 00303 /// \c lkptr<>'s to the same object. This should be an error! 00304 /// - Very usefull to avoid multiple destruction from unrelated \c lkptr<>'s 00305 /// that reference the same object. 00306 /// - Will not blend together null pointers. 00307 /// - Requires linear time in the number \c use_count() of the \c lkptr<>'s to merge. 00308 template <typename X> 00309 void base_lkptr<X>::merge( base_lkptr<X>& r ) { 00310 if ( this == &r ) { // avoid autolink problems 00311 return; 00312 } 00313 else if ( this->ptr == 0 ) { 00314 return; // avoid linking together null pointers 00315 } 00316 else if ( this->ptr != r.ptr ) { 00317 return; // never merge when they don´t reference the same object 00318 } 00319 { // avoid 4-nodes pointer problem 00320 base_lkptr<X> * r_prev = r.prev; 00321 #if 1 00322 while ( r_prev != &r ) { // never merge if they are already merged 00323 if ( r_prev==this ) { // already chained 00324 return; 00325 } // hopefully r's chain is shorter than this 00326 r_prev = r_prev->prev; 00327 } 00328 #else 00329 /// Sorry: doesn´t work !!! 00330 base_lkptr<X> * this_prev = this->prev; 00331 for ( int i=0; i<25 ; ++i ) { 00332 if ( (r_prev==this) || (this_prev==&r) ) { // already chained 00333 return; 00334 } // hopefully r's chain is shorter than this 00335 r_prev = r_prev->prev; 00336 this_prev = this_prev->prev; 00337 } 00338 #endif 00339 00340 r_prev = r.prev; 00341 base_lkptr<X> * this_next = this->next; 00342 00343 r.prev = this; 00344 this->next = &r; 00345 r_prev->next = this_next; 00346 this_next->prev = r_prev; 00347 } 00348 // NOTE: see 4-node chain problem at the end of this file 00349 } 00350 00351 template <typename X> 00352 int base_lkptr<X>::use_count() const throw() { 00353 int n = 1; // count "this" 00354 const base_lkptr* q = this->next; 00355 while (q != this) { // while´s can´t be inlined 00356 q = q->next; 00357 ++n; 00358 } 00359 return n; 00360 } 00361 00362 /// Verifies the invariant for class \c lkptr<X>. 00363 /// \see base_lkptr<X>::ok(). 00364 template <typename X> 00365 inline bool check_ok( const base_lkptr<X>& p ) throw() { return p.ok(); } 00366 00367 /** Verifies the invariant for class \c lkptr<X>. 00368 - Returns \c "true" when \c "p" contains a correct value. 00369 - It could return \c "true" even when it's value is corrupted. 00370 - it could never return if the value in \c "p" is corrupted. 00371 00372 \par Rep: Description with words. 00373 - Field \c "ptr" is the pointer to the referenced object. 00374 - All pointers that point to the same object are linked together. 00375 - The list is double linked to allow for O(1) insertion and removal. 00376 - There is no "first" or "last" element in the list. What it is 00377 important is to be "in" the list, not which position in it a 00378 particular \c lkptr<X> occupies. 00379 00380 \par Rep: Class diagram. 00381 \code 00382 <=================================> <=============> 00383 | p1 p2 p3 | | p4 | 00384 | +-+-+ +-+-+ +-+-+ | | +-+-+ | 00385 <===>|*|*|<===>|*|*|<===>|*|*|<===> <===>|*|*|<===> 00386 +-+-+ +-+-+ +-+-+ +-+-+ 00387 | * | | * | | * | | * | 00388 +-|-+ +-|-+ +-|-+ +-|-+ 00389 | | | | 00390 \|/ \|/ \|/ \|/ 00391 +----------------------+ +----------------------+ 00392 | Shared object | | Lonely Object | 00393 +----------------------+ +----------------------+ 00394 \endcode 00395 00396 \code 00397 +--------+-------+ "ptr" points to the object 00398 | prev | | 00399 +--------+ ptr + 00400 | next | | "next" is next in chain 00401 +--------+-------+ "prev" is previous in chain 00402 \endcode 00403 00404 \par The invariant: Description with words. 00405 */ 00406 template <typename X> 00407 bool base_lkptr<X>::ok() const throw() { 00408 { // check a single element double linked chain 00409 if ( (next==this) && (prev==this) ) { /* Ok */ } 00410 else if ( (next==this) || (prev==this) ) { 00411 return false; // because one of them must be a broken link 00412 /// - Invariant (1) (broken link): A unique pointer should be self-linked with 00413 /// both \c next && \c prev pointing to itself (\c this). 00414 } 00415 } 00416 00417 { // check the double linked chain 00418 const base_lkptr* frwd = this; 00419 const base_lkptr* back = this; 00420 do { 00421 if ( (frwd == frwd->next->prev) && (frwd == frwd->prev->next) ) { /* Ok */ } 00422 else { 00423 return false; 00424 /// - Invariant (2) (broken link): the double linked pointer chain can never be broken. 00425 } 00426 if ( this->ptr == frwd->ptr ) { /* Ok */ } 00427 else { 00428 return false; 00429 /// - Invariant (3) (broken ptr): Every pointer in the chain should reference 00430 /// the same object. 00431 } 00432 00433 if ( (back == back->next->prev) && (back == back->prev->next) ) { /* Ok */ } 00434 else { 00435 return false; 00436 } 00437 if ( this->ptr == back->ptr ) { /* Ok */ } 00438 else { 00439 return false; 00440 } 00441 00442 frwd = frwd->next; 00443 back = back->prev; 00444 } while (frwd != this && back != this); 00445 00446 if ( (frwd == this && back == this) ) { /* Ok */ } 00447 else { 00448 return false; 00449 /// - Invariant (4): chain is not a circular double linked chain 00450 } 00451 } 00452 00453 // This "YES" style of programming makes it easier to define the invariant 00454 // in positive terms. 00455 // - The "else" statement are executed when the invariant is broken. 00456 00457 { // check that the pointed object is correct 00458 #if 0 // NOT implemented 00459 // WHY? To avoid forcing the pointed type to have a check_ok() function 00460 bool check_ok( const X& ); // forward declaration 00461 if ( check_ok( * ptr ) ) { /* Ok */ } 00462 else { 00463 return false; /// - Invariant (5) (corrupt pointed object) 00464 } 00465 #endif 00466 } 00467 00468 if ( ptr==0 ) { // Check that the null pointer is in its own chain 00469 #ifdef lkptr_NULL_POINTERS_ARE_ALONE 00470 // There is really no harm if some null pointers are linked together. 00471 if ( (next==this) && (prev==this) ) { /* Ok */ } 00472 else { 00473 return false; 00474 /// - Invariant (6) (auto-link): A \c NULL pointer should be self-linked with 00475 /// both \c next && \c prev pointing to itself (\c this). 00476 } 00477 #endif 00478 } 00479 00480 return true; 00481 } 00482 00483 00484 template <typename X> 00485 class lkptr { 00486 base_lkptr<X> b; ///< Contains the 3 pointers for the \c lkptr<>. 00487 private: 00488 template <typename Y> friend class lkptr; 00489 public: 00490 typedef X element_type; ///< Standard name for the pointed object. 00491 typedef X value_type; ///< Standard name for the pointed object. 00492 typedef X * pointer; ///< Standard name for the pointer to the object. 00493 00494 /// \copydoc base_lkptr::base_lkptr(X*). 00495 explicit lkptr(X* p = 0) throw() : b(p) { } 00496 00497 /// \copydoc base_lkptr::base_lkptr(Y*). 00498 template <typename Y> 00499 explicit lkptr( Y* p ) throw() : b(p) { } 00500 00501 /// \copydoc base_lkptr::base_lkptr(const base_lkptr&). 00502 lkptr( const lkptr& r ) throw() : b(r.b) { } 00503 00504 /// \copydoc base_lkptr::base_lkptr(const base_lkptr<Y>&). 00505 template <typename Y> 00506 explicit lkptr( const lkptr<Y>& r ) throw() : b(r.b) { } 00507 00508 ~lkptr() { 00509 if ( b.prev == &b ) { 00510 if ( b.ptr!=0 ) { delete b.ptr; } 00511 } 00512 else { 00513 b.unlink(); 00514 } 00515 } ///< Destructor. 00516 00517 /// Copy operator: share the object with other pointers. 00518 lkptr& operator=( const lkptr& r ) { 00519 if (this == &r) { // avoid self - anhilation 00520 // don´t change 00521 } 00522 else { 00523 if ( b.prev == &(this->b) ) { // autolinked ==> unique() 00524 X* toDelete = b.ptr; 00525 b.ptr = 0; // restore invariant before "delete" 00526 if ( toDelete!=0 ) { 00527 delete toDelete; // this could throw an exception 00528 } 00529 } 00530 else { 00531 b.unlink(); 00532 } 00533 #ifdef lkptr_NULL_POINTERS_ARE_ALONE 00534 if ( r.ptr == 0) { 00535 b.prev = b.next = this; // restore invariant: unique in chain 00536 b.ptr = 0; // NULL pointers are always alone 00537 } 00538 else { 00539 b.acquire( const_cast< base_lkptr<X> * >( &r.b ) ); // r's chain fields will be changed 00540 } 00541 #else 00542 { 00543 b.acquire( const_cast< base_lkptr<X> * >( &r.b ) ); // r's chain fields will be changed 00544 } 00545 #endif 00546 } 00547 return *this; 00548 } 00549 00550 /// Copy operator from a derived clase: share the object with other pointers. 00551 /// - Will not copy when types are not compatible. 00552 /// - Make sure the destructor for the base class is virtual. 00553 template <typename Y> 00554 lkptr& operator=( const lkptr<Y>& r ) { 00555 X* ptr = dynamic_cast<X*>( r.b.ptr ); 00556 if ( 0!=ptr ) { // avoid invalid typecast 00557 this->operator=( * ( reinterpret_cast<const lkptr*>( &r ) ) ); 00558 } 00559 return *this; 00560 } 00561 00562 void swap( lkptr& r ) throw(); ///< Swaps with \c r. 00563 00564 X* get() const throw() { return b.get(); } ///< \copydoc base_lkptr::get() const. 00565 X& value() const throw() { return b.value(); } ///< \copydoc base_lkptr::value()const. 00566 X& operator*() const throw() { return b.operator*(); } ///< \copydoc base_lkptr::operator*() const. 00567 X* operator->() const throw() { return b.operator->(); } ///< \copydoc base_lkptr::operator->() const. 00568 // operator X* () const throw() { return b.operator X*(); } ///< \copydoc base_lkptr::operator X*() const. 00569 00570 bool isNull() const throw() { return b.isNull(); } ///< \copydoc base_lkptr::isNull(). 00571 bool unique() const throw() { return b.unique(); } ///< \copydoc base_lkptr::unique(). 00572 int use_count() const throw() { return b.use_count(); } ///< \copydoc base_lkptr::use_count(). 00573 00574 /// Releases the object. 00575 /// - Before: If this was the last reference, it also deletes the referenced object. 00576 /// - After: The pointer becomes \c NULL. 00577 /// - After: Equivalent to \c reset(0). 00578 void release() { 00579 if ( b.prev == &(this->b) ) { // autolinked ==> unique() 00580 X* toDelete = b.ptr; 00581 b.ptr = 0; // restore invariant before "delete" 00582 if ( toDelete!=0 ) { 00583 delete toDelete; // this could throw an exception 00584 } 00585 } 00586 else { // ! unique() ==> unlink from pointer chain 00587 b.unlink(); 00588 b.autolink(); // restore invariant: unique in chain 00589 b.ptr = 0; // isNull() is true 00590 } 00591 } 00592 00593 /// Resets the pointer so that it will point to \c "p". 00594 /// - Before: If this was the last reference, it also deletes the referenced object. 00595 /// - Before: \c "p==0" is a valid argument (\c NULL is ok). 00596 /// - After: The object pointed by \c "p" gets to be own by \c "this". 00597 /// - [DANGER] <code>V.reset( r.get() )</code> almost always is an error because 00598 /// both \c V and \c r will destroy the referenced object. Use <code>V = r</code>. 00599 /// \dontinclude figures.h \skipline struct Point 00600 /// \until struct Rectangle 00601 /// \dontinclude test_lkptr.cpp \skipline test::inheritance 00602 /// \until }} 00603 void reset(X* p=0) { 00604 #if 0 00605 if (ptr == p) { 00606 return; // avoid self - anhilation 00607 } 00608 #endif 00609 release(); 00610 b.ptr = p; 00611 } 00612 00613 /// <code>(*this) = r</code>. 00614 void reset( const lkptr& r ) { 00615 this->operator= ( r ); // necessary to mask out reset(X*) 00616 #if 0 00617 {/* Note: 00618 Automatic conversion into a pointer is discouraged because it can lead 00619 to serious errors. If the conversion lktpr<X>::operator X*() exists, it 00620 would convert any lkptr<X> into its X*, which makes very easy the 00621 following erroneous usage: 00622 tik.reset( tak.get() ); // [ERROR] tik.reset( tak.operator X*() ); 00623 This will causes double destruction of the pointed object because there 00624 are 2 unlinked lkptr<X>'s that own the same object. 00625 */ 00626 X* ptrX = new X(); 00627 lkptr<X> tik ( ptrX ); 00628 lkptr<X> tak; 00629 00630 tik = tak; assertTrue( tik.use_count() == 2 ); // ok 00631 tik.reset( tak.get() ); // [ERROR] tik.reset( tak.operator X*() ); 00632 assertTrue( tik.use_count() == 1 ); 00633 assertTrue( tak.use_count() == 1 ); // unlinked 00634 00635 assertTrue( tik.next != &tak ); // they are unlinked 00636 assertTrue( tak.prev != &tik ); 00637 assertTrue( tik.ptr == tak.ptr ); // both share the same object 00638 } // ptrX gets destroyed twice 00639 #endif 00640 } 00641 00642 /// <code>(*this) = r</code> [ from a derived class ]. 00643 template <typename Y> 00644 void reset( const lkptr<Y>& r ) { 00645 this->operator=( r ); 00646 } 00647 00648 #ifdef lkptr_MERGE_IS_PUBLIC 00649 void merge( lkptr& r ) { b.merge( r.b ); } ///< \copydoc merge( base_lkptr& ). 00650 void weak_release() { b.weak_release(); } ///< \copydoc weak_release( base_lkptr& ). 00651 #endif 00652 00653 bool ok() const throw() { return b.ok(); } ///< \copydoc base_lkptr::ok(). 00654 template <typename Y> friend bool check_ok( const lkptr<Y>& p ) throw(); 00655 00656 private: 00657 template <typename Y> friend class test_lkptr; ///< Test \c lkptr<X>. 00658 00659 #if 0 // doesn´t work 00660 private: 00661 array_lkptr<X>& 00662 operator=( const array_lkptr<X>& r ); ///< Forbid mixing \c lktpr<> with \c array_lktpr<>. 00663 void reset( const array_lkptr<X>& r ); ///< Forbid mixing \c lktpr<> with \c array_lktpr<>. 00664 void merge( const array_lkptr<X>& r ); ///< Forbid mixing \c lktpr<> with \c array_lktpr<>. 00665 #endif 00666 }; // class lkptr<> 00667 00668 /// Swaps with \c r. 00669 template <typename X> 00670 void lkptr<X>::swap( lkptr<X>& r ) throw() { 00671 lkptr tmp = *this; // Thanks, David 00672 *this = r; 00673 r = tmp; 00674 } 00675 00676 /// Swap <code> l <==> r </code>. 00677 template <typename X> 00678 inline void swap( lkptr<X>& l , lkptr<X>& r ) throw() { 00679 l.swap( r ); 00680 } 00681 00682 template <typename X> 00683 inline bool check_ok( const lkptr<X>& p ) throw() 00684 { return check_ok( p.b ); } ///< \copydoc check_ok(const base_lkptr<X>&). 00685 00686 /// <code> (p == q) </code> ??? 00687 template <typename X> 00688 inline bool operator<( const lkptr<X> & p, const lkptr<X> & q ) { 00689 return p.get() < q.get(); 00690 } 00691 00692 /// <code> (p == q) </code> ??? 00693 template <typename X> 00694 inline bool operator==( const lkptr<X> & p, const lkptr<X> & q ) { 00695 return p.get() == q.get(); 00696 } 00697 00698 /// <code> (p != q) </code> ??? 00699 template <typename X> 00700 inline bool operator!=( const lkptr<X> & p, const lkptr<X> & q ) { 00701 return ! (p == q); 00702 } 00703 00704 /* Note: 00705 The implementation for array_lkptr<> is almos equal to the implementation for lkptr<>. 00706 These are the differences: 00707 - Instead of "lkptr" the class name is "array_lkptr". 00708 - Instead of using "delete b.ptr" what is used is "delete [] b.ptr" (vector delete). 00709 - Instead of using "delete toDelete" what is used is delete [] toDelete" (vector delete). 00710 00711 It is NOT wise to derive these 2 implementations from base_lkptr<> because the 00712 compiler includes the copy operator=() for all the classes, and then it allows for 00713 errors like these: 00714 lkptr<E> lk; 00715 array_lkptr<E> vec; 00716 00717 vec = lk; // error: no match for 'operator=' in 'vec = lk' 00718 lk = vec; // error: no match for 'operator=' in 'lk = vec' 00719 lk.merge( vec ); // error: no matching function for call to lkptr<int>::merge(array_lkptr<int>&) 00720 vec.merge( lk ); // error: no matching function for call to array_lkptr<int>::merge(lkptr<int>&) 00721 lk.reset( vec ); // error: no matching function for call to lkptr<int>::reset(array_lkptr<int>&) 00722 vec.reset( lk ); // error: no matching function for call to array_lkptr<int>::reset(lkptr<int>&) 00723 00724 */ 00725 00726 template <typename X> 00727 class array_lkptr { 00728 base_lkptr<X> b; ///< Contains the 3 pointers for the \c array_lkptr<>. 00729 private: 00730 template <typename Y> friend class array_lkptr; 00731 public: 00732 typedef X element_type; ///< Standard name for the pointed object. 00733 typedef X value_type; ///< Standard name for the pointed object. 00734 typedef X * pointer; ///< Standard name for the pointer to the object. 00735 00736 /// V[i]. 00737 X& operator[]( int i ) { 00738 return this->b.ptr[i]; 00739 } 00740 00741 /// \copydoc base_lkptr::base_lkptr(X*). 00742 explicit array_lkptr(X* p = 0) throw() : b(p) { } 00743 00744 /// \copydoc base_lkptr::base_lkptr(Y*). 00745 template <typename Y> 00746 explicit array_lkptr( Y* p ) throw() : b(p) { } 00747 00748 /// \copydoc base_lkptr::base_lkptr(const base_lkptr&). 00749 array_lkptr( const array_lkptr& r ) throw() : b(r.b) { } 00750 00751 /// \copydoc base_lkptr::base_lkptr(const base_lkptr<Y>&). 00752 template <typename Y> 00753 explicit array_lkptr( const array_lkptr<Y>& r ) throw() : b(r.b) { } 00754 00755 ~array_lkptr() { 00756 if ( b.prev == &b ) { 00757 if ( b.ptr!=0 ) { delete [] b.ptr; } 00758 } 00759 else { 00760 b.unlink(); 00761 } 00762 } ///< Destructor. 00763 00764 /// Copy operator: share the object with other pointers. 00765 array_lkptr& operator=( const array_lkptr& r ) { 00766 if (this == &r) { // avoid self - anhilation 00767 // don´t change 00768 } 00769 else { 00770 if ( b.prev == &(this->b) ) { // autolinked ==> unique() 00771 X* toDelete = b.ptr; 00772 b.ptr = 0; // restore invariant before "delete" 00773 if ( toDelete!=0 ) { 00774 delete [] toDelete; // this could throw an exception 00775 } 00776 } 00777 else { 00778 b.unlink(); 00779 } 00780 #ifdef array_lkptr_NULL_POINTERS_ARE_ALONE 00781 if ( r.ptr == 0) { 00782 b.prev = b.next = this; // restore invariant: unique in chain 00783 b.ptr = 0; // NULL pointers are always alone 00784 } 00785 else { 00786 b.acquire( const_cast< base_lkptr<X> * >( &r.b ) ); // r's chain fields will be changed 00787 } 00788 #else 00789 { 00790 b.acquire( const_cast< base_lkptr<X> * >( &r.b ) ); // r's chain fields will be changed 00791 } 00792 #endif 00793 } 00794 return *this; 00795 } 00796 00797 /// Copy operator from a derived clase: share the object with other pointers. 00798 /// - Will not copy when types are not compatible. 00799 /// - Make sure the destructor for the base class is virtual. 00800 template <typename Y> 00801 array_lkptr& operator=( const array_lkptr<Y>& r ) { 00802 X* ptr = dynamic_cast<X*>( r.b.ptr ); 00803 if ( 0!=ptr ) { // avoid invalid typecast 00804 this->operator=( * ( reinterpret_cast<const array_lkptr*>( &r ) ) ); 00805 } 00806 return *this; 00807 } 00808 00809 void swap( array_lkptr& r ) throw(); ///< Swaps with \c r. 00810 00811 X* get() const throw() { return b.get(); } ///< \copydoc base_lkptr::get() const. 00812 X& value() const throw() { return b.value(); } ///< \copydoc base_lkptr::value() const. 00813 X& operator*() const throw() { return b.operator*(); } ///< \copydoc base_lkptr::operator*() const. 00814 X* operator->() const throw() { return b.operator->(); } ///< \copydoc base_lkptr::operator->() const. 00815 // operator X* () const throw() { return b.operator X*(); } ///< \copydoc base_lkptr::operator X*() const. 00816 00817 bool isNull() const throw() { return b.isNull(); } ///< \copydoc base_lkptr::isNull(). 00818 bool unique() const throw() { return b.unique(); } ///< \copydoc base_lkptr::unique(). 00819 int use_count() const throw() { return b.use_count(); } ///< \copydoc base_lkptr::use_count(). 00820 00821 /// Releases the object. 00822 /// - Before: If this was the last reference, it also deletes the referenced object. 00823 /// - After: The pointer becomes \c NULL. 00824 /// - After: Equivalent to \c reset(0). 00825 void release() { 00826 if ( b.prev == &(this->b) ) { // autolinked ==> unique() 00827 X* toDelete = b.ptr; 00828 b.ptr = 0; // restore invariant before "delete" 00829 if ( toDelete!=0 ) { 00830 delete [] toDelete; // this could throw an exception 00831 } 00832 } 00833 else { // ! unique() ==> unlink from pointer chain 00834 b.unlink(); 00835 b.autolink(); // restore invariant: unique in chain 00836 b.ptr = 0; // isNull() is true 00837 } 00838 } 00839 00840 /// Resets the pointer so that it will point to \c "p". 00841 /// - Before: If this was the last reference, it also deletes the referenced object. 00842 /// - Before: \c "p==0" is a valid argument (\c NULL is ok). 00843 /// - After: The object pointed by \c "p" gets to be own by \c "this". 00844 /// - [DANGER] <code>V.reset( r.get() )</code> almost always is an error because 00845 /// both \c V and \c r will destroy the referenced object. Use <code>V = r</code>. 00846 /// \dontinclude figures.h \skipline struct Point 00847 /// \until struct Rectangle 00848 /// \dontinclude test_lkptr.cpp \skipline test::inheritance 00849 /// \until }} 00850 void reset(X* p=0) { 00851 #if 0 00852 if (ptr == p) { 00853 return; // avoid self - anhilation 00854 } 00855 #endif 00856 release(); 00857 b.ptr = p; 00858 } 00859 00860 /// <code>(*this) = r</code>. 00861 void reset( const array_lkptr& r ) { 00862 this->operator= ( r ); // necessary to mask out reset(X*) 00863 #if 0 00864 {/* Note: 00865 Automatic conversion into a pointer is discouraged because it can lead 00866 to serious errors. If the conversion lktpr<X>::operator X*() exists, it 00867 would convert any array_lkptr<X> into its X*, which makes very easy the 00868 following erroneous usage: 00869 tik.reset( tak.get() ); // [ERROR] tik.reset( tak.operator X*() ); 00870 This will causes double destruction of the pointed object because there 00871 are 2 unlinked array_lkptr<X>'s that own the same object. 00872 */ 00873 X* ptrX = new X(); 00874 array_lkptr<X> tik ( ptrX ); 00875 array_lkptr<X> tak; 00876 00877 tik = tak; assertTrue( tik.use_count() == 2 ); // ok 00878 tik.reset( tak.get() ); // [ERROR] tik.reset( tak.operator X*() ); 00879 assertTrue( tik.use_count() == 1 ); 00880 assertTrue( tak.use_count() == 1 ); // unlinked 00881 00882 assertTrue( tik.next != &tak ); // they are unlinked 00883 assertTrue( tak.prev != &tik ); 00884 assertTrue( tik.ptr == tak.ptr ); // both share the same object 00885 } // ptrX gets destroyed twice 00886 #endif 00887 } 00888 00889 /// <code>(*this) = r</code> [ from a derived class ]. 00890 template <typename Y> 00891 void reset( const array_lkptr<Y>& r ) { 00892 this->operator=( r ); 00893 } 00894 00895 #ifdef array_lkptr_MERGE_IS_PUBLIC 00896 void merge( array_lkptr& r ) { b.merge( r.b ); } ///< \copydoc merge( base_lkptr& ). 00897 void weak_release() { b.weak_release(); } ///< \copydoc weak_release( base_lkptr& ). 00898 #endif 00899 00900 bool ok() const throw() { return b.ok(); } ///< \copydoc base_lkptr::ok(). 00901 template <typename Y> friend bool check_ok( const array_lkptr<Y>& p ) throw(); 00902 00903 private: 00904 template <typename Y> friend class base_lkptr; ///< Test \c array_lkptr<X>. 00905 00906 #if 0 // doesn´t work 00907 private: 00908 array_array_lkptr<X>& 00909 operator=( const array_array_lkptr<X>& r ); ///< Forbid mixing \c lktpr<> with \c array_lktpr<>. 00910 void reset( const array_array_lkptr<X>& r ); ///< Forbid mixing \c lktpr<> with \c array_lktpr<>. 00911 void merge( const array_array_lkptr<X>& r ); ///< Forbid mixing \c lktpr<> with \c array_lktpr<>. 00912 #endif 00913 }; // class array_lkptr<> 00914 00915 /// Swaps with \c r. 00916 template <typename X> 00917 void array_lkptr<X>::swap( array_lkptr<X>& r ) throw() { 00918 array_lkptr tmp = *this; // Thanks, David 00919 *this = r; 00920 r = tmp; 00921 } 00922 00923 /// Swap <code> l <==> r </code>. 00924 template <typename X> 00925 inline void swap( array_lkptr<X>& l , array_lkptr<X>& r ) throw() { 00926 l.swap( r ); 00927 } 00928 00929 template <typename X> 00930 inline bool check_ok( const array_lkptr<X>& p ) throw() 00931 { return check_ok( p.b ); } ///< \copydoc check_ok(const base_lkptr<X>&). 00932 00933 /// <code> (p == q) </code> ??? 00934 template <typename X> 00935 inline bool operator<( const array_lkptr<X> & p, const array_lkptr<X> & q ) { 00936 return p.get() < q.get(); 00937 } 00938 00939 /// <code> (p == q) </code> ??? 00940 template <typename X> 00941 inline bool operator==( const array_lkptr<X> & p, const array_lkptr<X> & q ) { 00942 return p.get() == q.get(); 00943 } 00944 00945 /// <code> (p != q) </code> ??? 00946 template <typename X> 00947 inline bool operator!=( const array_lkptr<X> & p, const array_lkptr<X> & q ) { 00948 return ! (p == q); 00949 } 00950 00951 00952 00953 /* NOTE: 00954 When [this] and [r] are in the same chain and the chain has 00955 4 nodes, executing the pointer assignment sequence in merge() 00956 results in the 4-node chain being splitted into 2 chains 00957 of 2-nodes each. 00958 00959 This 4-node chain diagram shows this special case, and shows 00960 why it is necessary to use a while() loop to implement merge(). 00961 00962 +---->----------------->---------+ 00963 this / | 00964 || / ++===<=================<===\ | 00965 || / || \\ | 00966 \/ / \/ \\ v 00967 +-----/-+-------+ +-------+-\\----+ 00968 | / | next | | | \\ | 00969 | [**] | [**] | | [**] | [**] | <== r 00970 | prev | || | | | | | 00971 +-------+--++---+ +---+---+-------+ 00972 ^ || | /\ 00973 | || | || 00974 | \/ v || 00975 +---+---+-------+ +-------+---++--+ 00976 | | | | | | || | 00977 | [**] | [**] |<------------+--[**] | [**] | <== r_prev 00978 | | \\ | | | | 00979 +-------+----\\-+ +-------+-------+ 00980 /\ \\ /\ 00981 || \\ || 00982 || \===>=================>===++ 00983 this_next 00984 00985 // Execute this code in the above 4-node chain: 00986 r.prev = this; 00987 this->next = &r; 00988 r_prev->next = this_next; 00989 this_next->prev = r_prev; 00990 00991 // The results is these 2 [broken] 2-node chains: 00992 00993 00994 +----->----------------->---------+ 00995 this / | 00996 || / ++===<=================<===\ | 00997 || / || \\ | 00998 \/ / \/ \\ v 00999 +----/--+-------+ +-------+-\\----+ 01000 | / | | | | \\ | 01001 | [**] | [**] |<------------+-[**] | [**] | <== r 01002 | | \\ | | | | 01003 +-------+----\\-+ +-------+-------+ 01004 \\ /\ 01005 \\ || 01006 \===>=================>===++ 01007 01008 01009 +----->----------------->---------+ 01010 / | 01011 / ++===<=================<===\ | 01012 / || \\ | 01013 / \/ \\ v 01014 +----/--+-------+ +-------+-\\----+ 01015 | / | | | | \\ | 01016 | [**] | [**] |<------------+-[**] | [**] | <== r_prev 01017 | | \\ | | | | 01018 +-------+----\\-+ +-------+-------+ 01019 /\ \\ /\ 01020 || \\ || 01021 || \===>=================>===++ 01022 this_next 01023 01024 */ 01025 01026 #endif // lkptr_h 01027 #undef COMPILER_lkptr // clean up your own dirt 01028 01029 // EOF: lkptr.h