00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00016
00017
00018
00019
00020 #include <loki/SmartPtr.h>
00021
00022 #include <cassert>
00023
00024
00025 #ifdef DO_EXTRA_LOKI_TESTS
00026 #include <iostream>
00027 #endif
00028
00029
00030
00031
00032 namespace Loki
00033 {
00034
00035 namespace Private
00036 {
00037
00038
00039
00040 RefLinkedBase::RefLinkedBase(const RefLinkedBase& rhs)
00041 {
00042 prev_ = &rhs;
00043 next_ = rhs.next_;
00044 prev_->next_ = this;
00045 next_->prev_ = this;
00046
00047 #ifdef DO_EXTRA_LOKI_TESTS
00048 assert( prev_->HasPrevNode( this ) );
00049 assert( next_->HasNextNode( this ) );
00050 assert( CountPrevCycle( this ) == CountNextCycle( this ) );
00051 #endif
00052 }
00053
00054
00055
00056 bool RefLinkedBase::Release()
00057 {
00058
00059 #ifdef DO_EXTRA_LOKI_TESTS
00060 assert( prev_->HasPrevNode( this ) );
00061 assert( next_->HasNextNode( this ) );
00062 assert( CountPrevCycle( this ) == CountNextCycle( this ) );
00063 #endif
00064
00065 if ( NULL == next_ )
00066 {
00067 assert( NULL == prev_ );
00068
00069
00070 return false;
00071 }
00072 else if (next_ == this)
00073 {
00074 assert(prev_ == this);
00075
00076 prev_ = NULL;
00077 next_ = NULL;
00078 return true;
00079 }
00080
00081 #ifdef DO_EXTRA_LOKI_TESTS
00082 assert( this != prev_ );
00083 assert( NULL != prev_ );
00084 assert( prev_->HasPrevNode( this ) );
00085 assert( next_->HasNextNode( this ) );
00086 #endif
00087
00088 prev_->next_ = next_;
00089 next_->prev_ = prev_;
00090
00091 #ifdef DO_EXTRA_LOKI_TESTS
00092 next_ = this;
00093 prev_ = this;
00094 assert( 1 == CountNextCycle( this ) );
00095 assert( 1 == CountPrevCycle( this ) );
00096 #endif
00097
00098 return false;
00099 }
00100
00101
00102
00103 void RefLinkedBase::Swap(RefLinkedBase& rhs)
00104 {
00105
00106 #ifdef DO_EXTRA_LOKI_TESTS
00107 assert( prev_->HasPrevNode( this ) );
00108 assert( next_->HasNextNode( this ) );
00109 assert( CountPrevCycle( this ) == CountNextCycle( this ) );
00110 #endif
00111
00112 if (next_ == this)
00113 {
00114 assert(prev_ == this);
00115 if (rhs.next_ == &rhs)
00116 {
00117 assert(rhs.prev_ == &rhs);
00118
00119 return;
00120 }
00121 prev_ = rhs.prev_;
00122 next_ = rhs.next_;
00123 prev_->next_ = next_->prev_ = this;
00124 rhs.next_ = rhs.prev_ = &rhs;
00125 return;
00126 }
00127 if (rhs.next_ == &rhs)
00128 {
00129 rhs.Swap(*this);
00130 return;
00131 }
00132 if (next_ == &rhs )
00133 {
00134 if ( prev_ == &rhs )
00135 return;
00136 std::swap(prev_, next_);
00137 std::swap(rhs.prev_, rhs.next_);
00138 std::swap(rhs.prev_, next_);
00139 std::swap(rhs.prev_->next_,next_->prev_);
00140 }
00141 else if ( prev_ == &rhs )
00142 {
00143 if ( next_ == &rhs )
00144 return;
00145 std::swap( prev_, next_ );
00146 std::swap( rhs.next_, rhs.prev_ );
00147 std::swap( rhs.next_, prev_ );
00148 std::swap( rhs.next_->prev_, prev_->next_ );
00149 }
00150 else
00151 {
00152 std::swap(prev_, rhs.prev_);
00153 std::swap(next_, rhs.next_);
00154 std::swap(prev_->next_, rhs.prev_->next_);
00155 std::swap(next_->prev_, rhs.next_->prev_);
00156 }
00157
00158 #ifdef DO_EXTRA_LOKI_TESTS
00159 assert( next_ == this ? prev_ == this : prev_ != this);
00160 assert( prev_ == this ? next_ == this : next_ != this);
00161 assert( prev_->HasPrevNode( this ) );
00162 assert( next_->HasNextNode( this ) );
00163 assert( CountPrevCycle( this ) == CountNextCycle( this ) );
00164 assert( rhs.prev_->HasPrevNode( &rhs ) );
00165 assert( rhs.next_->HasNextNode( &rhs ) );
00166 assert( CountPrevCycle( &rhs ) == CountNextCycle( &rhs ) );
00167 #endif
00168
00169 }
00170
00171
00172
00173 unsigned int RefLinkedBase::CountPrevCycle( const RefLinkedBase * pThis )
00174 {
00175 if ( NULL == pThis )
00176 return 0;
00177 const RefLinkedBase * p = pThis->prev_;
00178 if ( NULL == p )
00179 return 0;
00180 if ( pThis == p )
00181 return 1;
00182
00183 unsigned int count = 1;
00184 do
00185 {
00186 p = p->prev_;
00187 ++count;
00188 } while ( p != pThis );
00189
00190 return count;
00191 }
00192
00193
00194
00195 unsigned int RefLinkedBase::CountNextCycle( const RefLinkedBase * pThis )
00196 {
00197 if ( NULL == pThis )
00198 return 0;
00199 const RefLinkedBase * p = pThis->next_;
00200 if ( NULL == p )
00201 return 0;
00202 if ( pThis == p )
00203 return 1;
00204
00205 unsigned int count = 1;
00206 while ( p != pThis )
00207 {
00208 p = p->next_;
00209 ++count;
00210 }
00211
00212 return count;
00213 }
00214
00215
00216
00217 bool RefLinkedBase::HasPrevNode( const RefLinkedBase * p ) const
00218 {
00219 if ( this == p )
00220 return true;
00221 const RefLinkedBase * prev = prev_;
00222 if ( NULL == prev )
00223 return false;
00224 while ( prev != this )
00225 {
00226 if ( p == prev )
00227 return true;
00228 prev = prev->prev_;
00229 }
00230 return false;
00231 }
00232
00233
00234
00235 bool RefLinkedBase::HasNextNode( const RefLinkedBase * p ) const
00236 {
00237 if ( this == p )
00238 return true;
00239 const RefLinkedBase * next = next_;
00240 if ( NULL == next )
00241 return false;
00242 while ( next != this )
00243 {
00244 if ( p == next )
00245 return true;
00246 next = next->next_;
00247 }
00248 return false;
00249 }
00250
00251
00252
00253 bool RefLinkedBase::Merge( RefLinkedBase & rhs )
00254 {
00255
00256 if ( NULL == next_ )
00257 {
00258 assert( NULL == prev_ );
00259 return false;
00260 }
00261 RefLinkedBase * prhs = &rhs;
00262 if ( prhs == this )
00263 return true;
00264 if ( NULL == prhs->next_ )
00265 {
00266 assert( NULL == prhs->prev_ );
00267 return true;
00268 }
00269
00270 assert( CountPrevCycle( this ) == CountNextCycle( this ) );
00271 assert( CountPrevCycle( prhs ) == CountNextCycle( prhs ) );
00272
00273 if ( HasPrevNode( &rhs ) )
00274 {
00275 assert( HasNextNode( &rhs ) );
00276 return true;
00277 }
00278
00279 if ( prhs == prhs->next_ )
00280 {
00282 assert( prhs->prev_ == prhs );
00283 prhs->prev_ = prev_;
00284 prhs->next_ = this;
00285 prev_->next_ = prhs;
00286 prev_ = prhs;
00287 }
00288 else if ( this == next_ )
00289 {
00291 assert( prev_ == this );
00292 prev_ = prhs->prev_;
00293 next_ = prhs;
00294 prhs->prev_->next_ = this;
00295 prhs->prev_ = this;
00296 }
00297 else
00298 {
00299 next_->prev_ = prhs->prev_;
00300 prhs->prev_->next_ = prev_;
00301 next_ = prhs;
00302 prhs->prev_ = this;
00303 }
00304
00305 assert( CountPrevCycle( this ) == CountNextCycle( this ) );
00306 return true;
00307 }
00308
00309
00310
00311 }
00312
00313 }
00314