aboutsummaryrefslogtreecommitdiff
path: root/src/unstable/cachebase.h
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2014-07-22 16:39:01 +0000
committerMike Buland <eichlan@xagasoft.com>2014-07-22 16:39:01 +0000
commit21a4337dc2f969dc3ec81e6ba3170119bcb67016 (patch)
treeaf8077ea0e89ec29b499e46583f3de35d1b3103c /src/unstable/cachebase.h
parent6482ec1f7550f0fca153bd8f556327902c7afec8 (diff)
downloadlibbu++-21a4337dc2f969dc3ec81e6ba3170119bcb67016.tar.gz
libbu++-21a4337dc2f969dc3ec81e6ba3170119bcb67016.tar.bz2
libbu++-21a4337dc2f969dc3ec81e6ba3170119bcb67016.tar.xz
libbu++-21a4337dc2f969dc3ec81e6ba3170119bcb67016.zip
Deferred erase now works on cache entries. You can erase a cache entry while
it still has active references, and it will be safely cleaned up when the last reference is released.
Diffstat (limited to 'src/unstable/cachebase.h')
-rw-r--r--src/unstable/cachebase.h76
1 files changed, 67 insertions, 9 deletions
diff --git a/src/unstable/cachebase.h b/src/unstable/cachebase.h
index 1584246..b17d377 100644
--- a/src/unstable/cachebase.h
+++ b/src/unstable/cachebase.h
@@ -29,6 +29,7 @@ namespace Bu
29 private: 29 private:
30 CacheEntry( obtype *pObject ) : 30 CacheEntry( obtype *pObject ) :
31 iRefCount( 0 ), 31 iRefCount( 0 ),
32 bDeleted( false ),
32 pObject( pObject ) 33 pObject( pObject )
33 { 34 {
34 } 35 }
@@ -78,10 +79,29 @@ namespace Bu
78 return bRet; 79 return bRet;
79 } 80 }
80 81
82 bool isDeleted()
83 {
84 mEntry.lock();
85 bool bRet = bDeleted;
86 mEntry.unlock();
87 return bRet;
88 }
89
90 // Indicates that the entry was both deleted
91 // and has a refcount of zero
92 bool isReadyForCleanup()
93 {
94 mEntry.lock();
95 bool bRet = bDeleted && iRefCount == 0;
96 mEntry.unlock();
97 return bRet;
98 }
99
81 private: 100 private:
82 mutable Bu::Mutex mEntry; 101 mutable Bu::Mutex mEntry;
83 mutable Bu::Mutex mObject; 102 mutable Bu::Mutex mObject;
84 int iRefCount; 103 int iRefCount;
104 bool bDeleted;
85 obtype *pObject; 105 obtype *pObject;
86 }; 106 };
87 107
@@ -104,7 +124,7 @@ namespace Bu
104 obtype * &rpData ) 124 obtype * &rpData )
105 { 125 {
106 if( pCache == NULL ) 126 if( pCache == NULL )
107 throw Bu::ExceptionBase("Invalid pointer"); 127 throw Bu::ExceptionBase("Invalid cache pointer");
108 128
109 if( !rpData ) 129 if( !rpData )
110 { 130 {
@@ -241,6 +261,12 @@ namespace Bu
241 return pCache->template cast<obtype, castto>( *this ); 261 return pCache->template cast<obtype, castto>( *this );
242 } 262 }
243 263
264 template<typename castto>
265 CachePtr<keytype, castto, basetype> cast() const
266 {
267 return pCache->template cast<obtype, castto>( *this );
268 }
269
244 bool operator==( const MyType &rhs ) const 270 bool operator==( const MyType &rhs ) const
245 { 271 {
246 return pCache == rhs.pCache && 272 return pCache == rhs.pCache &&
@@ -410,19 +436,46 @@ namespace Bu
410 else 436 else
411 return CachePtr<keytype, castto, obtype>( this, ptr.kId ); 437 return CachePtr<keytype, castto, obtype>( this, ptr.kId );
412 } 438 }
439
440 template<typename supertype, typename castto>
441 CachePtr<keytype, castto, obtype> cast( const CachePtr<keytype, supertype, obtype> &ptr )
442 {
443 if( ptr.pEnt )
444 return CachePtr<keytype, castto, obtype>( this, ptr.pEnt, ptr.kId );
445 else
446 return CachePtr<keytype, castto, obtype>( this, ptr.kId );
447 }
413 448
414 /** 449 /**
415 * Removes an item from the cache. 450 * Removes an item from the cache.
416 * This routine calls eraseNow for now. Later the intention is that 451 * The object in question can have references to it, and those
417 * this function will always succeed. It will remove the object from 452 * references will still work after the erase is called. When erase
418 * the backing store and the active tables. It will not be able to 453 * is called the object is immediately removed from the backing store
419 * be requested again, and all changes will be ignored. When the 454 * as well as from the main index. At that point existing references
420 * object's last references are released the memory will be freed 455 * can be used as normal, but when the last reference is released
421 * automatically. 456 * the memory will be automatically cleaned up.
422 */ 457 */
423 void erase( const keytype &key ) 458 void erase( const keytype &key )
424 { 459 {
425 eraseNow( key ); 460 Bu::ReadWriteMutex::WriteLocker wl( mCacheEntry );
461 if( hCacheEntry.has( key ) )
462 {
463 Entry *pEnt = hCacheEntry.get( key );
464 pEnt->mEntry.lock();
465 if( pEnt->iRefCount == 0 )
466 {
467 pEnt->mEntry.unlock();
468 delete pEnt->pObject;
469 delete pEnt;
470 }
471 else
472 {
473 pEnt->bDeleted = true;
474 pEnt->mEntry.unlock();
475 }
476 hCacheEntry.erase( key );
477 }
478 _erase( key );
426 } 479 }
427 480
428 /** 481 /**
@@ -467,8 +520,13 @@ namespace Bu
467 return pEnt; 520 return pEnt;
468 } 521 }
469 522
470 void releaseRef( Entry * )//pEnt ) 523 void releaseRef( Entry *pEnt )
471 { 524 {
525 if( pEnt->isReadyForCleanup() )
526 {
527 delete pEnt->pObject;
528 delete pEnt;
529 }
472 } 530 }
473 531
474 void objectChanged( const keytype &k ) 532 void objectChanged( const keytype &k )