00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00012
00013
00014
00015
00016 #include <loki/StrongPtr.h>
00017
00018 #include <memory.h>
00019 #ifdef DO_EXTRA_LOKI_TESTS
00020 #include <cassert>
00021 #endif
00022
00023 #include <loki/SmallObj.h>
00024
00025
00026
00027
00028 namespace Loki
00029 {
00030
00031
00032
00033 TwoRefCounts::TwoRefCounts( bool strong )
00034 : m_counts( NULL )
00035 {
00036 void * temp = SmallObject<>::operator new(
00037 sizeof(Loki::Private::TwoRefCountInfo) );
00038 #ifdef DO_EXTRA_LOKI_TESTS
00039 assert( temp != 0 );
00040 #endif
00041 m_counts = new ( temp ) Loki::Private::TwoRefCountInfo( strong );
00042 }
00043
00044
00045
00046 TwoRefCounts::TwoRefCounts( const void * p, bool strong )
00047 : m_counts( NULL )
00048 {
00049 void * temp = SmallObject<>::operator new(
00050 sizeof(Loki::Private::TwoRefCountInfo) );
00051 #ifdef DO_EXTRA_LOKI_TESTS
00052 assert( temp != 0 );
00053 #endif
00054 void * p2 = const_cast< void * >( p );
00055 m_counts = new ( temp ) Loki::Private::TwoRefCountInfo( p2, strong );
00056 }
00057
00058
00059
00060 void TwoRefCounts::Increment( bool strong )
00061 {
00062 if ( strong )
00063 {
00064 m_counts->IncStrongCount();
00065 }
00066 else
00067 {
00068 m_counts->IncWeakCount();
00069 }
00070 }
00071
00072
00073
00074 bool TwoRefCounts::Decrement( bool strong )
00075 {
00076 if ( strong )
00077 {
00078 m_counts->DecStrongCount();
00079 }
00080 else
00081 {
00082 m_counts->DecWeakCount();
00083 }
00084 return !m_counts->HasStrongPointer();
00085 }
00086
00087
00088
00089 void TwoRefCounts::Swap( TwoRefCounts & rhs )
00090 {
00091 std::swap( m_counts, rhs.m_counts );
00092 }
00093
00094
00095
00096 void TwoRefCounts::ZapPointer( void )
00097 {
00098 #ifdef DO_EXTRA_LOKI_TESTS
00099 assert( !m_counts->HasStrongPointer() );
00100 #endif
00101 if ( m_counts->HasWeakPointer() )
00102 {
00103 m_counts->ZapPointer();
00104 }
00105 else
00106 {
00107 SmallObject<>::operator delete ( m_counts,
00108 sizeof(Loki::Private::TwoRefCountInfo) );
00109 m_counts = NULL;
00110 }
00111 }
00112
00113
00114
00115
00116 TwoRefLinks::TwoRefLinks( const void * p, bool strong )
00117 : m_pointer( const_cast< void * >( p ) )
00118 , m_strong( strong )
00119 {
00120 m_prev = m_next = this;
00121 #ifdef DO_EXTRA_LOKI_TESTS
00122 assert( CountPrevCycle( this ) == CountNextCycle( this ) );
00123 #endif
00124 }
00125
00126
00127
00128 TwoRefLinks::TwoRefLinks( const TwoRefLinks & rhs, bool strong )
00129 : m_pointer( rhs.m_pointer )
00130 , m_prev( const_cast< TwoRefLinks * >( &rhs ) )
00131 , m_next( rhs.m_next )
00132 , m_strong( strong )
00133 {
00134 m_prev->m_next = this;
00135 m_next->m_prev = this;
00136
00137 #ifdef DO_EXTRA_LOKI_TESTS
00138 assert( m_prev->HasPrevNode( this ) );
00139 assert( m_next->HasNextNode( this ) );
00140 assert( rhs.m_next->HasNextNode( this ) );
00141 assert( rhs.m_prev->HasPrevNode( this ) );
00142 assert( CountPrevCycle( this ) == CountNextCycle( this ) );
00143 assert( CountPrevCycle( this ) == CountNextCycle( &rhs ) );
00144 assert( AllNodesHaveSamePointer() );
00145 #endif
00146 }
00147
00148
00149
00150 void TwoRefLinks::SetPointer( void * p )
00151 {
00152 TwoRefLinks * node = m_prev;
00153 if ( ( this == node ) || ( 0 == node ) )
00154 return;
00155
00156 #ifdef DO_EXTRA_LOKI_TESTS
00157 assert( m_prev->HasPrevNode( this ) );
00158 assert( m_next->HasNextNode( this ) );
00159 assert( CountPrevCycle( this ) == CountNextCycle( this ) );
00160 assert( AllNodesHaveSamePointer() );
00161 #endif
00162
00163 while ( node != this )
00164 {
00165 node->m_pointer = p;
00166 node = node->m_next;
00167 }
00168 m_pointer = node;
00169
00170 #ifdef DO_EXTRA_LOKI_TESTS
00171 assert( m_prev->HasPrevNode( this ) );
00172 assert( m_next->HasNextNode( this ) );
00173 assert( CountPrevCycle( this ) == CountNextCycle( this ) );
00174 assert( AllNodesHaveSamePointer() );
00175 #endif
00176 }
00177
00178
00179
00180 bool TwoRefLinks::Release( bool strong )
00181 {
00182
00183 (void)strong;
00184 #ifdef DO_EXTRA_LOKI_TESTS
00185 assert( strong == m_strong );
00186 assert( m_prev->HasPrevNode( this ) );
00187 assert( m_next->HasNextNode( this ) );
00188 assert( CountPrevCycle( this ) == CountNextCycle( this ) );
00189 assert( AllNodesHaveSamePointer() );
00190 #endif
00191
00192 if ( NULL == m_next )
00193 {
00194 #ifdef DO_EXTRA_LOKI_TESTS
00195 assert( NULL == m_prev );
00196 #endif
00197
00198
00199 return false;
00200 }
00201 else if (m_next == this)
00202 {
00203 #ifdef DO_EXTRA_LOKI_TESTS
00204 assert(m_prev == this);
00205 #endif
00206
00207 m_prev = NULL;
00208 m_next = NULL;
00209
00210 return true;
00211 }
00212
00213 #ifdef DO_EXTRA_LOKI_TESTS
00214 assert( this != m_prev );
00215 assert( NULL != m_prev );
00216 assert( m_prev->HasPrevNode( this ) );
00217 assert( m_next->HasNextNode( this ) );
00218 #endif
00219
00220
00221 if ( HasStrongPointer() )
00222 {
00223
00224 m_prev->m_next = m_next;
00225 m_next->m_prev = m_prev;
00226 return false;
00227 }
00228
00229 return true;
00230 }
00231
00232
00233
00234 void TwoRefLinks::ZapAllNodes( void )
00235 {
00236 TwoRefLinks * p = m_prev;
00237 if ( ( this == p ) || ( 0 == p ) )
00238 return;
00239 #ifdef DO_EXTRA_LOKI_TESTS
00240 assert( AllNodesHaveSamePointer() );
00241 #endif
00242
00243 while ( p != this )
00244 {
00245 TwoRefLinks * p1 = p->m_prev;
00246 p->m_pointer = 0;
00247 p->m_next = p;
00248 p->m_prev = p;
00249 p = p1;
00250 }
00251 m_pointer = 0;
00252 }
00253
00254
00255
00256 void TwoRefLinks::Swap( TwoRefLinks & rhs )
00257 {
00258
00259 #ifdef DO_EXTRA_LOKI_TESTS
00260 assert( m_prev->HasPrevNode( this ) );
00261 assert( m_next->HasNextNode( this ) );
00262 assert( CountPrevCycle( this ) == CountNextCycle( this ) );
00263 assert( AllNodesHaveSamePointer() );
00264 assert( rhs.AllNodesHaveSamePointer() );
00265 #endif
00266
00267 std::swap( rhs.m_pointer, m_pointer );
00268 if (m_next == this)
00269 {
00270 #ifdef DO_EXTRA_LOKI_TESTS
00271
00272 assert(m_prev == this);
00273 #endif
00274 if (rhs.m_next == &rhs)
00275 {
00276 #ifdef DO_EXTRA_LOKI_TESTS
00277 assert(rhs.m_prev == &rhs);
00278 #endif
00279
00280 return;
00281 }
00282 m_prev = rhs.m_prev;
00283 m_next = rhs.m_next;
00284 m_prev->m_next = m_next->m_prev = this;
00285 rhs.m_next = rhs.m_prev = &rhs;
00286 return;
00287 }
00288 if (rhs.m_next == &rhs)
00289 {
00290 #ifdef DO_EXTRA_LOKI_TESTS
00291
00292 assert( rhs.m_prev == &rhs );
00293 #endif
00294 rhs.m_prev = m_prev;
00295 rhs.m_next = m_next;
00296 m_prev->m_next = m_next->m_prev = &rhs;
00297 m_next = m_prev = this;
00298 return;
00299 }
00300 if (m_next == &rhs )
00301 {
00302 if ( m_prev == &rhs )
00303 return;
00304 std::swap(m_prev, m_next);
00305 std::swap(rhs.m_prev, rhs.m_next);
00306 std::swap(rhs.m_prev, m_next);
00307 std::swap(rhs.m_prev->m_next,m_next->m_prev);
00308 }
00309 else if ( m_prev == &rhs )
00310 {
00311 if ( m_next == &rhs )
00312 return;
00313 std::swap( m_prev, m_next );
00314 std::swap( rhs.m_next, rhs.m_prev );
00315 std::swap( rhs.m_next, m_prev );
00316 std::swap( rhs.m_next->m_prev, m_prev->m_next );
00317 }
00318 else
00319 {
00320 std::swap(m_prev, rhs.m_prev);
00321 std::swap(m_next, rhs.m_next);
00322 std::swap(m_prev->m_next, rhs.m_prev->m_next);
00323 std::swap(m_next->m_prev, rhs.m_next->m_prev);
00324 }
00325
00326 #ifdef DO_EXTRA_LOKI_TESTS
00327 assert( m_next == this ? m_prev == this : m_prev != this);
00328 assert( m_prev == this ? m_next == this : m_next != this);
00329 assert( m_prev->HasPrevNode( this ) );
00330 assert( m_next->HasNextNode( this ) );
00331 assert( CountPrevCycle( this ) == CountNextCycle( this ) );
00332 assert( rhs.m_prev->HasPrevNode( &rhs ) );
00333 assert( rhs.m_next->HasNextNode( &rhs ) );
00334 assert( CountPrevCycle( &rhs ) == CountNextCycle( &rhs ) );
00335 assert( AllNodesHaveSamePointer() );
00336 assert( rhs.AllNodesHaveSamePointer() );
00337 #endif
00338
00339 }
00340
00341
00342
00343 bool TwoRefLinks::AllNodesHaveSamePointer( void ) const
00344 {
00345 const TwoRefLinks * next = m_next;
00346 if ( NULL == next )
00347 return true;
00348 do
00349 {
00350 if ( next->m_pointer != m_pointer )
00351 return false;
00352 next = next->m_next;
00353 } while ( next != this );
00354 return true;
00355 }
00356
00357
00358
00359 unsigned int TwoRefLinks::CountPrevCycle( const TwoRefLinks * pThis )
00360 {
00361 if ( NULL == pThis )
00362 return 0;
00363 const TwoRefLinks * p = pThis->m_prev;
00364 if ( NULL == p )
00365 return 0;
00366 if ( pThis == p )
00367 return 1;
00368
00369 unsigned int count = 1;
00370 do
00371 {
00372 p = p->m_prev;
00373 ++count;
00374 } while ( p != pThis );
00375
00376 return count;
00377 }
00378
00379
00380
00381 unsigned int TwoRefLinks::CountNextCycle( const TwoRefLinks * pThis )
00382 {
00383 if ( NULL == pThis )
00384 return 0;
00385 const TwoRefLinks * p = pThis->m_next;
00386 if ( NULL == p )
00387 return 0;
00388 if ( pThis == p )
00389 return 1;
00390
00391 unsigned int count = 1;
00392 while ( p != pThis )
00393 {
00394 p = p->m_next;
00395 ++count;
00396 }
00397
00398 return count;
00399 }
00400
00401
00402
00403 bool TwoRefLinks::HasPrevNode( const TwoRefLinks * p ) const
00404 {
00405 if ( this == p )
00406 return true;
00407 const TwoRefLinks * prev = m_prev;
00408 if ( NULL == prev )
00409 return false;
00410 while ( prev != this )
00411 {
00412 if ( p == prev )
00413 return true;
00414 prev = prev->m_prev;
00415 }
00416 return false;
00417 }
00418
00419
00420
00421 bool TwoRefLinks::HasNextNode( const TwoRefLinks * p ) const
00422 {
00423 if ( this == p )
00424 return true;
00425 const TwoRefLinks * next = m_next;
00426 if ( NULL == next )
00427 return false;
00428 while ( next != this )
00429 {
00430 if ( p == next )
00431 return true;
00432 next = next->m_next;
00433 }
00434 return false;
00435 }
00436
00437
00438
00439 bool TwoRefLinks::HasStrongPointer( void ) const
00440 {
00441 const TwoRefLinks * next = m_next;
00442 if ( NULL == next )
00443 return false;
00444 while ( next != this )
00445 {
00446 if ( next->m_strong )
00447 return true;
00448 next = next->m_next;
00449 }
00450 return false;
00451 }
00452
00453
00454
00455 bool TwoRefLinks::Merge( TwoRefLinks & rhs )
00456 {
00457
00458 if ( NULL == m_next )
00459 {
00460 #ifdef DO_EXTRA_LOKI_TESTS
00461 assert( NULL == m_prev );
00462 #endif
00463 return false;
00464 }
00465 TwoRefLinks * prhs = &rhs;
00466 if ( prhs == this )
00467 return true;
00468 if ( NULL == prhs->m_next )
00469 {
00470 #ifdef DO_EXTRA_LOKI_TESTS
00471 assert( NULL == prhs->m_prev );
00472 #endif
00473 return true;
00474 }
00475
00476 #ifdef DO_EXTRA_LOKI_TESTS
00477 assert( CountPrevCycle( this ) == CountNextCycle( this ) );
00478 assert( CountPrevCycle( prhs ) == CountNextCycle( prhs ) );
00479 #endif
00480
00481 if ( HasPrevNode( &rhs ) )
00482 {
00483 #ifdef DO_EXTRA_LOKI_TESTS
00484 assert( HasNextNode( &rhs ) );
00485 #endif
00486 return true;
00487 }
00488
00489 if ( prhs == prhs->m_next )
00490 {
00492 #ifdef DO_EXTRA_LOKI_TESTS
00493 assert( prhs->m_prev == prhs );
00494 #endif
00495 prhs->m_prev = m_prev;
00496 prhs->m_next = this;
00497 m_prev->m_next = prhs;
00498 m_prev = prhs;
00499 }
00500 else if ( this == m_next )
00501 {
00503 #ifdef DO_EXTRA_LOKI_TESTS
00504 assert( m_prev == this );
00505 #endif
00506 m_prev = prhs->m_prev;
00507 m_next = prhs;
00508 prhs->m_prev->m_next = this;
00509 prhs->m_prev = this;
00510 }
00511 else
00512 {
00513 m_next->m_prev = prhs->m_prev;
00514 prhs->m_prev->m_next = m_prev;
00515 m_next = prhs;
00516 prhs->m_prev = this;
00517 }
00518
00519
00520 #ifdef DO_EXTRA_LOKI_TESTS
00521 assert( CountPrevCycle( this ) == CountNextCycle( this ) );
00522 #endif
00523
00524 return true;
00525 }
00526
00527
00528
00529 }
00530