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 00013 \author Adolfo Di Mare <adolfo@di-mare.com> 00014 \date 2007 00015 */ 00016 00017 /// MOD this when your compiler does compile this correctly. 00018 #undef COMPILER_lkptr 00019 00020 #ifdef _MSC_VER 00021 #if _MSC_VER >= 1300 // .net Microsoft Visual Studio C++ 00022 #define COMPILER_lkptr 00023 #endif 00024 #endif 00025 00026 #ifdef __BORLANDC__ // Borland C++ 00027 #if (__BORLANDC__ <= 0x0410) // BC++ v3.1 or earlier 00028 #undef COMPILER_lkptr 00029 #endif 00030 #endif 00031 00032 #ifdef __GNUC__ // GNU C++ 00033 #define COMPILER_lkptr 00034 #endif 00035 00036 #ifndef COMPILER_lkptr 00037 #error Compiler not yet supported // emit error 00038 #define lkptr_h // avoid file inclussion || compilation 00039 #endif 00040 00041 #ifndef lkptr_h 00042 #define lkptr_h ///< Avoid multiple file inclusion 00043 00044 template <class X> class lkptr; // class declaration follows 00045 00046 /** These smart pointer share the object they point to. 00047 Only after the last pointer releases its reference will the object be deleted. 00048 - Whenever the object will be changed by one of the pointers, all the 00049 other pointers will also see the change. 00050 - The implementation stores three pointers for every \c lkptr, 00051 but does not allocate anything on the free store. 00052 - Every \c lkptr is implemented using 3 internal pointers which 00053 makes it 3 times as big as a regular pointer. In exchange, 00054 automatic garbage collection is provided by the C++ 00055 constructor - destructor protocol of execution. 00056 - These pointers are double linked together. When only one pointer 00057 is in the chain, then the object will be deleted if the pointer 00058 releases it. Otherwise, the object will not be deleted because 00059 the other pointers in the chain are still referencing it. 00060 - These pointers are not intrusive, because they do not need an 00061 extra field in the pointed object to keep track of how many 00062 pointers reference the same object. 00063 - These pointers do not allocate extra memory to keep track of the 00064 reference count, because the linked list itself binds together 00065 all pointers that reference the same object. 00066 - A diagram for the pointer chain is shown in the documentation for 00067 method \c ok(). 00068 - Many of the pointer operators will never throw exceptions (hence 00069 the \c "throw()" especification in the method signature). 00070 - Memory leaks are extremely rare. Reference counting/linking can 00071 leak in the case of circular references (i.e., when the pointed 00072 object itself contains a counted/linked pointer, which points 00073 to an object that contains the original counted/linked pointer). 00074 - These pointers cannot be used in ROM memory because they modify 00075 each other when double linking, even if they are \c const. 00076 00077 \par Usage: 00078 \code 00079 void foo() { 00080 lkptr<AnyClass> p(new AnyClass); // "p" is one smart-pointer 00081 lkptr<AnyClass> q; // "q" is the other smart-pointer 00082 00083 p->DoSomething(); // no syntax change when using pointers 00084 q = p; // share the object 00085 q->Change(); // both "*p" && "*q" get changed 00086 p = q; // both still point to the same object 00087 lkptr<AnyClass> r = p; // The 3 of them share the same object 00088 00089 // delete p; // No need to worry about destruction 00090 // delete q; // the lkptr<> destructor will handle deletions for you. 00091 // delete r; 00092 } 00093 \endcode 00094 00095 - This work is based on Sharon's paper: 00096 - "Smart Pointers - What, Why, Which?" 00097 - http://ootips.org/yonat/4dev/smart-pointers.html 00098 - Yonat Sharon <yonat@ootips.org> 00099 - 1999. 00100 */ 00101 template <class X> 00102 class lkptr { 00103 private: // Rep fields have the "m_" prefix 00104 X * m_ptr; ///< Pointer to referenced object (can be a \c NULL pointer). 00105 lkptr * m_prev; ///< Next in pointer chain. 00106 lkptr * m_next; ///< Previous in pointer chain. 00107 public: 00108 typedef X element_type; ///< Standard name for the pointed object. 00109 typedef X value_type; ///< Standard name for the pointed object. 00110 00111 /// Default constructor and constructor from a regular pointer. 00112 explicit lkptr(X* p = 0) throw() : m_ptr(p) { m_prev = m_next = this; } 00113 ~lkptr() { fast_release(); } ///< Destructor. Delete only if last reference. 00114 00115 /// Copy constructor: share the object with other pointers. 00116 lkptr( const lkptr& r ) throw() { acquire( const_cast<lkptr*>( &r ) ); } 00117 /// Copy operator: share the object with other pointers. 00118 lkptr& operator=( const lkptr& r ) { 00119 if (this != &r) { // avoid self - anhilation 00120 fast_release(); // all the fields are in a broken state 00121 #ifdef lkptr_NULL_POINTERS_ARE_ALONE 00122 if ( r.m_ptr == 0) { 00123 m_prev = m_next = this; // restore invariant: unique in chain 00124 m_ptr = 0; // NULL pointers are always alone 00125 } 00126 else { 00127 acquire( const_cast< lkptr<X> * >( &r ) ); // r's chain fields will be changed 00128 } 00129 #else 00130 acquire( const_cast< lkptr<X> * >( &r ) ); // r's chain fields will be changed 00131 #endif 00132 } 00133 return *this; 00134 /* NOTE: 00135 A lkptr<D> will be implicitly converted to a lkptr<B> 00136 if a D* can be converted to a B*. ( D ~~ Derived ... B ~~ Base ) 00137 */ 00138 } 00139 void swap( lkptr & r ) throw(); 00140 // Pointer access operators (these never throw exceptions) 00141 X* get() const throw() { return m_ptr; } ///< Returns a pointer to referenced object. 00142 X& value() const throw() { return *m_ptr; } ///< Returns the referenced object. 00143 X& operator*() const throw() { return *m_ptr; } ///< Returns the referenced object. 00144 X* operator->() const throw() { return m_ptr; } ///< Returns a pointer to referenced object. 00145 operator X* () const throw() { return m_ptr; } ///< Returns a pointer to referenced object. 00146 00147 /// Returns \c true if the object pointed is null and \c false otherwise. 00148 bool isNull() const throw() { return m_ptr == 0; } 00149 00150 /// Return \c "true" when only one pointer references the object. 00151 bool unique() const throw() { return ( m_prev == this ); } 00152 00153 /// Returns how many pointers are sharing the object referenced by \c "this". 00154 int use_count() const throw(); 00155 00156 /// Releases the object. 00157 /// - Before: If this was the last reference, it also deletes the referenced object. 00158 /// - After: The pointer becomes \c NULL. 00159 /// - After: Equivalent to \c reset(0). 00160 void release() { 00161 fast_release(); // all the fields are in a broken state 00162 m_prev = m_next = this; // restore invariant: unique in chain 00163 m_ptr = 0; 00164 } 00165 00166 /// Releases the object. 00167 /// - Before: If this was the last reference, it will not delete the referenced object. 00168 /// - After: The pointer becomes \c NULL. 00169 /// - After: Simliar to \c reset(0) (with no delete). 00170 /// - Difference: never deletes the pointed object. 00171 void weak_release() { 00172 m_prev->m_next = m_next; // unlink from pointer chaing 00173 m_next->m_prev = m_prev; 00174 m_prev = m_next = this; // restore invariant: unique in chain 00175 m_ptr = 0; 00176 } 00177 00178 /// Resets the pointer so that it will point to \c "p". 00179 /// - Before: If this was the last reference, it also deletes the referenced object. 00180 /// - Before: \c "p==0" is a valid argument (\c NULL is ok). 00181 /// - After: The object pointed by \c "p" gets to be own by \c "this". 00182 void reset(X* p=0) { 00183 if (m_ptr == p) { 00184 return; // avoid self - anhilation 00185 } 00186 fast_release(); // all the fields are in a broken state 00187 m_prev = m_next = this; // restore invariant: unique in chain 00188 m_ptr = p; 00189 } 00190 00191 bool ok() const throw(); 00192 template <class Y> friend bool check_ok( const lkptr<Y>& p ) throw(); 00193 00194 private: 00195 /// Makes \c this->m_ptr point to \c r.m_ptr. 00196 /// - Insert \c "this" after \c "r" in the double chained pointer list. 00197 /// - If called after \c fast_release() will restore the invariant into \c "this". 00198 /// - Will link (this <--> r) even when r->m_ptr is a \c NULL pointer. 00199 void acquire(lkptr* r) throw() { 00200 m_ptr = r->m_ptr; // reference r's object 00201 m_next = r->m_next; 00202 m_next->m_prev = this; // 4 assignments to change the 4 next+prev chain pointers 00203 m_prev = r; 00204 r->m_next = this; 00205 // To double link with the list, "*r" must be changed. But the whole 00206 // implementation is easier if "*r" is const. 00207 } 00208 00209 /// Releases the object. 00210 /// - If \c this->m_ptr is the last reference, it also deletes the object. 00211 /// - Leaves all the fields in \c "this" in a broken state. 00212 /// - Caller must ensure that all the fields get good values after invocation. 00213 void fast_release() { 00214 if ( m_prev == this ) { // auto-linked ==> unique() 00215 if ( m_ptr!=0 ) { 00216 delete m_ptr; // this could throw an exception 00217 } 00218 } 00219 else { // ! unique() ==> unlink from pointer chain 00220 m_prev->m_next = m_next; 00221 m_next->m_prev = m_prev; 00222 } 00223 // leaves all the fields in a broken state: 00224 // m_prev = m_next = this; // set-all to nil pointer 00225 // m_ptr = 0; 00226 } 00227 00228 template <class Y> friend class test_lkptr; ///< Test \c lkptr<X>. 00229 }; // class lkptr 00230 00231 /// Swaps with \c r. 00232 template <class X> 00233 void lkptr<X>::swap ( lkptr<X>& r ) throw() { 00234 #if 1 // David 00235 lkptr tmp = *this; 00236 *this = r; 00237 r = tmp; 00238 #else // Adolfo 00239 if ( r.m_next == this || r.m_prev == this ) { // they are chained together 00240 return; // they both must point to same object 00241 } 00242 { // swap pointers 00243 X* tmp = this->m_ptr; 00244 m_ptr = r.m_ptr; 00245 r.m_ptr = tmp; 00246 } 00247 00248 if ( m_prev == this ) { 00249 if ( r.m_prev == & r ) { 00250 return; // both are already alone by themselves 00251 } 00252 else { // "*this" is alone but "r" is not 00253 this->m_next = r.m_next; 00254 this->m_prev = r.m_prev; 00255 r.m_next->m_prev = this; 00256 r.m_prev->m_next = this; 00257 r.m_next = r.m_prev = & r; // "r" becomes alone 00258 } 00259 } 00260 else if ( r.m_prev == & r ) { // "r" is alone but "*this" is not 00261 r.m_next = this->m_next; 00262 r.m_prev = this->m_prev; 00263 this->m_next->m_prev = & r; 00264 this->m_prev->m_next = & r; 00265 m_next = m_prev = this; // "*this" becomes alone 00266 } 00267 else { // general case: neither is alone 00268 { // set the pointers for the other nodes 00269 this->m_prev->m_next = & r; 00270 this->m_next->m_prev = & r; 00271 r.m_next->m_prev = this; 00272 r.m_prev->m_next = this; 00273 } 00274 { // swap this->m_prev <==> r.m_prev 00275 lkptr * tmp = this->m_prev; 00276 this->m_prev = r.m_prev; 00277 r.m_prev = tmp; 00278 } 00279 { // swap this->m_next <==> r.m_next 00280 lkptr * tmp = this->m_next; 00281 this->m_next = r.m_next; 00282 r.m_next = tmp; 00283 } 00284 } 00285 #endif 00286 } 00287 00288 /// <code> (p == q) </code> ??? 00289 template <class X> 00290 bool operator== ( const lkptr<X> & p, const lkptr<X> & q ) { 00291 return p.get() == q.get(); 00292 } 00293 00294 /// <code> (p != q) </code> ??? 00295 template <class X> 00296 bool operator!= ( const lkptr<X> & p, const lkptr<X> & q ) { 00297 return ! (p == q); 00298 } 00299 00300 template <class X> 00301 int lkptr<X>::use_count() const throw() { 00302 int n = 1; // count "this" 00303 const lkptr* q = this->m_next; 00304 while (q != this) { // while´s can´t be inlined 00305 q = q->m_next; 00306 ++n; 00307 } 00308 return n; 00309 } 00310 00311 /// Verifies the invariant for class \c lkptr<Y>. 00312 /// \see lkptr<Y>::ok(). 00313 template <class Y> 00314 inline bool check_ok( const lkptr<Y>& p ) throw() { return p.ok(); } 00315 00316 /** Verifies the invariant for class \c lkptr<X>. 00317 - Returns \c "true" when \c "p" contains a correct value. 00318 - It could return \c "true" even when it's value is corrupted. 00319 - it could never return if the value in \c "p" is corrupted. 00320 00321 \par Rep: Description with words. 00322 - Field \c "m_ptr" is the pointer to the referenced object. 00323 - All pointers that point to the same object are linked together. 00324 - The list is double linked to allow for O(1) insertion and removal. 00325 - There is no "first" or "last" element in the list. What it is 00326 important is to be "in" the list, not which position in it a 00327 particular \c lkptr<X> occupies. 00328 00329 \par Rep: Class diagram. 00330 \code 00331 <=================================> <=============> 00332 | p1 p2 p3 | | p4 | 00333 | +-+-+ +-+-+ +-+-+ | | +-+-+ | 00334 <===>|*|*|<===>|*|*|<===>|*|*|<===> <===>|*|*|<===> 00335 +-+-+ +-+-+ +-+-+ +-+-+ 00336 | * | | * | | * | | * | 00337 +-|-+ +-|-+ +-|-+ +-|-+ 00338 | | | | 00339 \|/ \|/ \|/ \|/ 00340 +----------------------+ +----------------------+ 00341 | Shared object | | Lonely Object | 00342 +----------------------+ +----------------------+ 00343 \endcode 00344 00345 \code 00346 +--------+-------+ "m_ptr" points to the object 00347 | m_prev | | 00348 +--------+ m_ptr + 00349 | m_next | | "m_next" is next in chain 00350 +--------+-------+ "m_prev" is previous in chain 00351 \endcode 00352 00353 \par The invariant: Description with words. 00354 */ 00355 template <class X> 00356 bool lkptr<X>::ok() const throw() { 00357 { // check a single element double linked chain 00358 if ( (m_next==this) && (m_prev==this) ) { /* Ok */ } 00359 else if ( (m_next==this) || (m_prev==this) ) { 00360 return false; // because one of them must be a broken link 00361 /// - Invariant (1) (broken link): A unique pointer should be self-linked with 00362 /// both \c m_next && \c m_prev pointing to itself (\c this). 00363 } 00364 } 00365 00366 { // check the double linked chain 00367 const lkptr* q = this; 00368 do { 00369 if ( (q == q->m_next->m_prev) && (q == q->m_prev->m_next) ) { /* Ok */ } 00370 else { 00371 return false; 00372 /// - Invariant (2) (broken link): the double linked pointer can never be broken. 00373 } 00374 if (this->m_ptr == q->m_ptr) { /* Ok */ } 00375 else { 00376 return false; 00377 /// - Invariant (3) (broken m_ptr): Every pointer in the chain should reference 00378 /// the same object. 00379 } 00380 q = q->m_next; 00381 } while (q != this); 00382 } 00383 00384 // This "YES" style of programming makes it easier to define the invariant 00385 // in positive terms. 00386 // - The "else" statement are executed when the invariant is broken. 00387 00388 { // check that the pointed object is correct 00389 #if 0 // NOT implemented 00390 // WHY? To avoid forcing the pointed type to have a check_ok() function 00391 bool check_ok( const X& ); // forward declaration 00392 if ( check_ok( * m_ptr ) ) { /* Ok */ } 00393 else { 00394 return false; /// - Invariant (4) (corrupt pointed object) 00395 } 00396 #endif 00397 } 00398 00399 if ( m_ptr==0 ) { // Check that the null pointer is in its own chain 00400 #ifdef lkptr_NULL_POINTERS_ARE_ALONE 00401 // There is really no harm if some null pointers are linked together. 00402 if ( (m_next==this) && (m_prev==this) ) { /* Ok */ } 00403 else { 00404 return false; 00405 /// - Invariant (5) (auto-link): A \c NULL pointer should be self-linked with 00406 /// both \c m_next && \c m_prev pointing to itself (\c this). 00407 } 00408 #endif 00409 } 00410 00411 return true; 00412 } 00413 00414 #endif // lkptr_h 00415 #undef COMPILER_lkptr 00416 00417 // EOF: lkptr.h
1.5.6