From a7c44a1356a8ee1384d70dd98941e00c89ec2702 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 12 Mar 2013 05:26:44 +0000 Subject: Bu::Uuid now supports being formatted, it uses the standard toString() method. The new cache is really coming along now. --- src/tests/cache.cpp | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 212 insertions(+), 6 deletions(-) (limited to 'src/tests/cache.cpp') diff --git a/src/tests/cache.cpp b/src/tests/cache.cpp index 5731a6a..6fc4e4a 100644 --- a/src/tests/cache.cpp +++ b/src/tests/cache.cpp @@ -7,6 +7,9 @@ #include #include +#include +#include + // // New Cache Implementation // @@ -57,7 +60,8 @@ class CachePtr { friend class CacheBase; private: - CachePtr( CacheBase *pCache, obtype *pData, const keytype &kId ) : + CachePtr( CacheBase *pCache, obtype *pData, + const keytype &kId ) : pCache( pCache ), kId( kId ), pData( pData ) @@ -72,10 +76,43 @@ private: } public: + CachePtr() : + pCache( NULL ), + pData( NULL ) + { + } + virtual ~CachePtr() { } + const keytype &getKey() const + { + return kId; + } + + obtype &operator*() + { + checkRef(); + return pData; + } + + obtype *operator->() + { + checkRef(); + return pData; + } + +private: + void checkRef() + { + if( pCache == NULL ) + throw Bu::ExceptionBase("Invalid pointer"); + + if( !pData ) + pData = pCache->getRef( kId ); + } + private: CacheBase *pCache; mutable keytype kId; @@ -86,6 +123,7 @@ private: template class CacheBase { +friend class CachePtr; public: CacheBase() { @@ -95,17 +133,145 @@ public: { } + typedef Bu::List KeyList; + + CachePtr insert( const obtype *pObject ) + { + CacheEntry *pEnt = addEntry( pObject ); + + pEnt->incRef(); + return CachePtr( this, pEnt->getPtr(), pObject->getKey() ); + } + + template + CachePtr insert( const supertype *pObject ) + { + const obtype *pCast = dynamic_cast( pObject ); + if( pCast == NULL ) + throw std::bad_cast(); + + CacheEntry *pEnt = addEntry( pCast ); + + pEnt->incRef(); + return CachePtr( this, pObject, pObject->getKey() ); + } + + CachePtr get( const keytype &key ) + { + CacheEntry *pEnt = getEntry( key ); + pEnt->incRef(); + return CachePtr( this, pEnt->getPtr(), key ); + } + + template + CachePtr get( const keytype &key ) + { + CacheEntry *pEnt = getEntry( key ); + pEnt->incRef(); + supertype *pCast = dynamic_cast( pEnt->getPtr() ); + if( pCast == NULL ) + { + pEnt->decRef(); + throw std::bad_cast(); + } + return CachePtr( this, pCast, key ); + } + + virtual KeyList getKeys() const=0; + + virtual void sync()=0; + protected: + obtype *getRef( const keytype &k ) + { + CacheEntry *pEnt = getEntry( k ); + pEnt->incRef(); + return pEnt->getPtr(); + } + void objectChanged( const keytype &k ) { } + class CacheEntry + { + public: + CacheEntry( obtype *pObject ) : + iRefCount( 0 ), + pObject( pObject ) + { + } + + void incRef() + { + mEntry.lock(); + iRefCount++; + mEntry.unlock(); + } + + bool decRef() + { + mEntry.lock(); + iRefCount--; + bool bRet = iRefCount > 0; + mEntry.unlock(); + return bRet; + } + + obtype *getPtr() + { + return pObject; + } + + private: + Bu::Mutex mEntry; + int iRefCount; + obtype *pObject; + }; + protected: - virtual void _create( obtype *o )=0; + virtual void _create( const obtype *o )=0; virtual void _erase( const keytype &k )=0; virtual obtype *_load( const keytype &k )=0; - virtual void _save( obtype *o )=0; + virtual void _save( const obtype *o )=0; + +private: + CacheEntry *addEntry( const obtype *pObject ) + { + CacheEntry *pEnt = new CacheEntry( const_cast(pObject) ); + mCacheEntry.lockWrite(); + hCacheEntry.insert( pObject->getKey(), pEnt ); + mCacheEntry.unlockWrite(); + _create( pObject ); + + return pEnt; + } + + CacheEntry *getEntry( const keytype &k ) + { + CacheEntry *pEnt = NULL; + try + { + Bu::ReadWriteMutex::ReadLocker rl( mCacheEntry ); + pEnt = hCacheEntry.get( k ); + } + catch(...) + { + // try to load the object from the backing store + obtype *pObject = _load( k ); + pEnt = new CacheEntry( pObject ); + Bu::ReadWriteMutex::WriteLocker wl( mCacheEntry ); + hCacheEntry.insert( k, pEnt ); + } + return pEnt; + } + +private: + typedef Bu::Hash CacheEntryHash; + CacheEntryHash hCacheEntry; + Bu::ReadWriteMutex mCacheEntry; + }; template @@ -116,6 +282,7 @@ public: sStore( sStore ), mStore( sStore, iBlockSize, iPreallocate ) { + Bu::ReadWriteMutex::WriteLocker wl( rwStore ); try { Bu::MyriadStream ms = mStore.openStream( 1 ); @@ -135,10 +302,29 @@ public: virtual ~MyriadCache() { + sync(); + } + + using typename CacheBase::KeyList; + + virtual KeyList getKeys() const + { + Bu::ReadWriteMutex::ReadLocker rl( rwStore ); + return hIndex.getKeys(); + } + + virtual void sync() + { + Bu::ReadWriteMutex::ReadLocker wl( rwStore ); + Bu::MyriadStream ms = mStore.openStream( 1 ); + Bu::Archive ar( ms, Bu::Archive::save ); + ar << hIndex; + ar.close(); + ms.setSize( ms.tell() ); } protected: - virtual void _create( obtype *o ) + virtual void _create( const obtype *o ) { hIndex.insert( o->getKey(), mStore.createStream() ); _save( o ); @@ -159,7 +345,7 @@ protected: return ret; } - virtual void _save( obtype *o ) + virtual void _save( const obtype *o ) { Bu::MyriadStream ms = mStore.openStream( hIndex.get( o->getKey() ) ); { @@ -173,6 +359,7 @@ private: Bu::Stream &sStore; Bu::Myriad mStore; Bu::Hash hIndex; + mutable Bu::ReadWriteMutex rwStore; }; // @@ -203,6 +390,11 @@ public: return uId; } + Bu::String getName() + { + return sName; + } + private: Bu::Uuid uId; Bu::String sName; @@ -218,10 +410,24 @@ Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const Something &s ) return ar << s.uId << s.sName; } +typedef CachePtr SomethingPtr; +typedef MyriadCache SomethingCache; + int main() { Bu::File fStore("test.myr", Bu::File::Create|Bu::File::ReadWrite); - MyriadCache c( fStore ); + SomethingCache c( fStore ); + + SomethingPtr ptr = c.insert( new Something("Bob") ); + + Bu::println("Something[%1]: %2").arg( ptr.getKey() ).arg(ptr->getName()); + + SomethingCache::KeyList lKeys = c.getKeys(); + for( SomethingCache::KeyList::iterator i = lKeys.begin(); i; i++ ) + { + Bu::println(" - %1").arg( *i ); + } + return 0; } -- cgit v1.2.3