lkptr - simple reference LinKed PoinTeR:
lkptr.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines