diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/tests/cache.cpp | 218 | ||||
| -rw-r--r-- | src/unstable/uuid.cpp | 9 | ||||
| -rw-r--r-- | src/unstable/uuid.h | 2 |
3 files changed, 221 insertions, 8 deletions
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 @@ | |||
| 7 | #include <bu/streamstack.h> | 7 | #include <bu/streamstack.h> |
| 8 | #include <bu/readwritemutex.h> | 8 | #include <bu/readwritemutex.h> |
| 9 | 9 | ||
| 10 | #include <bu/sio.h> | ||
| 11 | #include <bu/string.h> | ||
| 12 | |||
| 10 | // | 13 | // |
| 11 | // New Cache Implementation | 14 | // New Cache Implementation |
| 12 | // | 15 | // |
| @@ -57,7 +60,8 @@ class CachePtr | |||
| 57 | { | 60 | { |
| 58 | friend class CacheBase<keytype, basetype>; | 61 | friend class CacheBase<keytype, basetype>; |
| 59 | private: | 62 | private: |
| 60 | CachePtr( CacheBase<keytype, basetype> *pCache, obtype *pData, const keytype &kId ) : | 63 | CachePtr( CacheBase<keytype, basetype> *pCache, obtype *pData, |
| 64 | const keytype &kId ) : | ||
| 61 | pCache( pCache ), | 65 | pCache( pCache ), |
| 62 | kId( kId ), | 66 | kId( kId ), |
| 63 | pData( pData ) | 67 | pData( pData ) |
| @@ -72,10 +76,43 @@ private: | |||
| 72 | } | 76 | } |
| 73 | 77 | ||
| 74 | public: | 78 | public: |
| 79 | CachePtr() : | ||
| 80 | pCache( NULL ), | ||
| 81 | pData( NULL ) | ||
| 82 | { | ||
| 83 | } | ||
| 84 | |||
| 75 | virtual ~CachePtr() | 85 | virtual ~CachePtr() |
| 76 | { | 86 | { |
| 77 | } | 87 | } |
| 78 | 88 | ||
| 89 | const keytype &getKey() const | ||
| 90 | { | ||
| 91 | return kId; | ||
| 92 | } | ||
| 93 | |||
| 94 | obtype &operator*() | ||
| 95 | { | ||
| 96 | checkRef(); | ||
| 97 | return pData; | ||
| 98 | } | ||
| 99 | |||
| 100 | obtype *operator->() | ||
| 101 | { | ||
| 102 | checkRef(); | ||
| 103 | return pData; | ||
| 104 | } | ||
| 105 | |||
| 106 | private: | ||
| 107 | void checkRef() | ||
| 108 | { | ||
| 109 | if( pCache == NULL ) | ||
| 110 | throw Bu::ExceptionBase("Invalid pointer"); | ||
| 111 | |||
| 112 | if( !pData ) | ||
| 113 | pData = pCache->getRef( kId ); | ||
| 114 | } | ||
| 115 | |||
| 79 | private: | 116 | private: |
| 80 | CacheBase<keytype, basetype> *pCache; | 117 | CacheBase<keytype, basetype> *pCache; |
| 81 | mutable keytype kId; | 118 | mutable keytype kId; |
| @@ -86,6 +123,7 @@ private: | |||
| 86 | template<typename keytype, typename obtype> | 123 | template<typename keytype, typename obtype> |
| 87 | class CacheBase | 124 | class CacheBase |
| 88 | { | 125 | { |
| 126 | friend class CachePtr<keytype, obtype>; | ||
| 89 | public: | 127 | public: |
| 90 | CacheBase() | 128 | CacheBase() |
| 91 | { | 129 | { |
| @@ -95,17 +133,145 @@ public: | |||
| 95 | { | 133 | { |
| 96 | } | 134 | } |
| 97 | 135 | ||
| 136 | typedef Bu::List<keytype> KeyList; | ||
| 137 | |||
| 138 | CachePtr<keytype, obtype> insert( const obtype *pObject ) | ||
| 139 | { | ||
| 140 | CacheEntry *pEnt = addEntry( pObject ); | ||
| 141 | |||
| 142 | pEnt->incRef(); | ||
| 143 | return CachePtr<keytype, obtype>( this, pEnt->getPtr(), pObject->getKey() ); | ||
| 144 | } | ||
| 145 | |||
| 146 | template<typename supertype> | ||
| 147 | CachePtr<keytype, supertype, obtype> insert( const supertype *pObject ) | ||
| 148 | { | ||
| 149 | const obtype *pCast = dynamic_cast<const obtype *>( pObject ); | ||
| 150 | if( pCast == NULL ) | ||
| 151 | throw std::bad_cast(); | ||
| 152 | |||
| 153 | CacheEntry *pEnt = addEntry( pCast ); | ||
| 154 | |||
| 155 | pEnt->incRef(); | ||
| 156 | return CachePtr<keytype, supertype, obtype>( this, pObject, pObject->getKey() ); | ||
| 157 | } | ||
| 158 | |||
| 159 | CachePtr<keytype, obtype> get( const keytype &key ) | ||
| 160 | { | ||
| 161 | CacheEntry *pEnt = getEntry( key ); | ||
| 162 | pEnt->incRef(); | ||
| 163 | return CachePtr<keytype, obtype>( this, pEnt->getPtr(), key ); | ||
| 164 | } | ||
| 165 | |||
| 166 | template<typename supertype> | ||
| 167 | CachePtr<keytype, supertype, obtype> get( const keytype &key ) | ||
| 168 | { | ||
| 169 | CacheEntry *pEnt = getEntry( key ); | ||
| 170 | pEnt->incRef(); | ||
| 171 | supertype *pCast = dynamic_cast<supertype *>( pEnt->getPtr() ); | ||
| 172 | if( pCast == NULL ) | ||
| 173 | { | ||
| 174 | pEnt->decRef(); | ||
| 175 | throw std::bad_cast(); | ||
| 176 | } | ||
| 177 | return CachePtr<keytype, supertype, obtype>( this, pCast, key ); | ||
| 178 | } | ||
| 179 | |||
| 180 | virtual KeyList getKeys() const=0; | ||
| 181 | |||
| 182 | virtual void sync()=0; | ||
| 183 | |||
| 98 | protected: | 184 | protected: |
| 185 | obtype *getRef( const keytype &k ) | ||
| 186 | { | ||
| 187 | CacheEntry *pEnt = getEntry( k ); | ||
| 188 | pEnt->incRef(); | ||
| 189 | return pEnt->getPtr(); | ||
| 190 | } | ||
| 191 | |||
| 99 | void objectChanged( const keytype &k ) | 192 | void objectChanged( const keytype &k ) |
| 100 | { | 193 | { |
| 101 | } | 194 | } |
| 102 | 195 | ||
| 196 | class CacheEntry | ||
| 197 | { | ||
| 198 | public: | ||
| 199 | CacheEntry( obtype *pObject ) : | ||
| 200 | iRefCount( 0 ), | ||
| 201 | pObject( pObject ) | ||
| 202 | { | ||
| 203 | } | ||
| 204 | |||
| 205 | void incRef() | ||
| 206 | { | ||
| 207 | mEntry.lock(); | ||
| 208 | iRefCount++; | ||
| 209 | mEntry.unlock(); | ||
| 210 | } | ||
| 211 | |||
| 212 | bool decRef() | ||
| 213 | { | ||
| 214 | mEntry.lock(); | ||
| 215 | iRefCount--; | ||
| 216 | bool bRet = iRefCount > 0; | ||
| 217 | mEntry.unlock(); | ||
| 218 | return bRet; | ||
| 219 | } | ||
| 220 | |||
| 221 | obtype *getPtr() | ||
| 222 | { | ||
| 223 | return pObject; | ||
| 224 | } | ||
| 225 | |||
| 226 | private: | ||
| 227 | Bu::Mutex mEntry; | ||
| 228 | int iRefCount; | ||
| 229 | obtype *pObject; | ||
| 230 | }; | ||
| 231 | |||
| 103 | protected: | 232 | protected: |
| 104 | virtual void _create( obtype *o )=0; | 233 | virtual void _create( const obtype *o )=0; |
| 105 | virtual void _erase( const keytype &k )=0; | 234 | virtual void _erase( const keytype &k )=0; |
| 106 | 235 | ||
| 107 | virtual obtype *_load( const keytype &k )=0; | 236 | virtual obtype *_load( const keytype &k )=0; |
| 108 | virtual void _save( obtype *o )=0; | 237 | virtual void _save( const obtype *o )=0; |
| 238 | |||
| 239 | private: | ||
| 240 | CacheEntry *addEntry( const obtype *pObject ) | ||
| 241 | { | ||
| 242 | CacheEntry *pEnt = new CacheEntry( const_cast<obtype *>(pObject) ); | ||
| 243 | mCacheEntry.lockWrite(); | ||
| 244 | hCacheEntry.insert( pObject->getKey(), pEnt ); | ||
| 245 | mCacheEntry.unlockWrite(); | ||
| 246 | _create( pObject ); | ||
| 247 | |||
| 248 | return pEnt; | ||
| 249 | } | ||
| 250 | |||
| 251 | CacheEntry *getEntry( const keytype &k ) | ||
| 252 | { | ||
| 253 | CacheEntry *pEnt = NULL; | ||
| 254 | try | ||
| 255 | { | ||
| 256 | Bu::ReadWriteMutex::ReadLocker rl( mCacheEntry ); | ||
| 257 | pEnt = hCacheEntry.get( k ); | ||
| 258 | } | ||
| 259 | catch(...) | ||
| 260 | { | ||
| 261 | // try to load the object from the backing store | ||
| 262 | obtype *pObject = _load( k ); | ||
| 263 | pEnt = new CacheEntry( pObject ); | ||
| 264 | Bu::ReadWriteMutex::WriteLocker wl( mCacheEntry ); | ||
| 265 | hCacheEntry.insert( k, pEnt ); | ||
| 266 | } | ||
| 267 | return pEnt; | ||
| 268 | } | ||
| 269 | |||
| 270 | private: | ||
| 271 | typedef Bu::Hash<keytype, CacheEntry *> CacheEntryHash; | ||
| 272 | CacheEntryHash hCacheEntry; | ||
| 273 | Bu::ReadWriteMutex mCacheEntry; | ||
| 274 | |||
| 109 | }; | 275 | }; |
| 110 | 276 | ||
| 111 | template<typename keytype, typename obtype> | 277 | template<typename keytype, typename obtype> |
| @@ -116,6 +282,7 @@ public: | |||
| 116 | sStore( sStore ), | 282 | sStore( sStore ), |
| 117 | mStore( sStore, iBlockSize, iPreallocate ) | 283 | mStore( sStore, iBlockSize, iPreallocate ) |
| 118 | { | 284 | { |
| 285 | Bu::ReadWriteMutex::WriteLocker wl( rwStore ); | ||
| 119 | try | 286 | try |
| 120 | { | 287 | { |
| 121 | Bu::MyriadStream ms = mStore.openStream( 1 ); | 288 | Bu::MyriadStream ms = mStore.openStream( 1 ); |
| @@ -135,10 +302,29 @@ public: | |||
| 135 | 302 | ||
| 136 | virtual ~MyriadCache() | 303 | virtual ~MyriadCache() |
| 137 | { | 304 | { |
| 305 | sync(); | ||
| 306 | } | ||
| 307 | |||
| 308 | using typename CacheBase<keytype,obtype>::KeyList; | ||
| 309 | |||
| 310 | virtual KeyList getKeys() const | ||
| 311 | { | ||
| 312 | Bu::ReadWriteMutex::ReadLocker rl( rwStore ); | ||
| 313 | return hIndex.getKeys(); | ||
| 314 | } | ||
| 315 | |||
| 316 | virtual void sync() | ||
| 317 | { | ||
| 318 | Bu::ReadWriteMutex::ReadLocker wl( rwStore ); | ||
| 319 | Bu::MyriadStream ms = mStore.openStream( 1 ); | ||
| 320 | Bu::Archive ar( ms, Bu::Archive::save ); | ||
| 321 | ar << hIndex; | ||
| 322 | ar.close(); | ||
| 323 | ms.setSize( ms.tell() ); | ||
| 138 | } | 324 | } |
| 139 | 325 | ||
| 140 | protected: | 326 | protected: |
| 141 | virtual void _create( obtype *o ) | 327 | virtual void _create( const obtype *o ) |
| 142 | { | 328 | { |
| 143 | hIndex.insert( o->getKey(), mStore.createStream() ); | 329 | hIndex.insert( o->getKey(), mStore.createStream() ); |
| 144 | _save( o ); | 330 | _save( o ); |
| @@ -159,7 +345,7 @@ protected: | |||
| 159 | return ret; | 345 | return ret; |
| 160 | } | 346 | } |
| 161 | 347 | ||
| 162 | virtual void _save( obtype *o ) | 348 | virtual void _save( const obtype *o ) |
| 163 | { | 349 | { |
| 164 | Bu::MyriadStream ms = mStore.openStream( hIndex.get( o->getKey() ) ); | 350 | Bu::MyriadStream ms = mStore.openStream( hIndex.get( o->getKey() ) ); |
| 165 | { | 351 | { |
| @@ -173,6 +359,7 @@ private: | |||
| 173 | Bu::Stream &sStore; | 359 | Bu::Stream &sStore; |
| 174 | Bu::Myriad mStore; | 360 | Bu::Myriad mStore; |
| 175 | Bu::Hash<keytype, int> hIndex; | 361 | Bu::Hash<keytype, int> hIndex; |
| 362 | mutable Bu::ReadWriteMutex rwStore; | ||
| 176 | }; | 363 | }; |
| 177 | 364 | ||
| 178 | // | 365 | // |
| @@ -203,6 +390,11 @@ public: | |||
| 203 | return uId; | 390 | return uId; |
| 204 | } | 391 | } |
| 205 | 392 | ||
| 393 | Bu::String getName() | ||
| 394 | { | ||
| 395 | return sName; | ||
| 396 | } | ||
| 397 | |||
| 206 | private: | 398 | private: |
| 207 | Bu::Uuid uId; | 399 | Bu::Uuid uId; |
| 208 | Bu::String sName; | 400 | Bu::String sName; |
| @@ -218,10 +410,24 @@ Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const Something &s ) | |||
| 218 | return ar << s.uId << s.sName; | 410 | return ar << s.uId << s.sName; |
| 219 | } | 411 | } |
| 220 | 412 | ||
| 413 | typedef CachePtr<Bu::Uuid, Something> SomethingPtr; | ||
| 414 | typedef MyriadCache<Bu::Uuid, Something> SomethingCache; | ||
| 415 | |||
| 221 | int main() | 416 | int main() |
| 222 | { | 417 | { |
| 223 | Bu::File fStore("test.myr", Bu::File::Create|Bu::File::ReadWrite); | 418 | Bu::File fStore("test.myr", Bu::File::Create|Bu::File::ReadWrite); |
| 224 | MyriadCache<Bu::Uuid, Something> c( fStore ); | 419 | SomethingCache c( fStore ); |
| 420 | |||
| 421 | SomethingPtr ptr = c.insert( new Something("Bob") ); | ||
| 422 | |||
| 423 | Bu::println("Something[%1]: %2").arg( ptr.getKey() ).arg(ptr->getName()); | ||
| 424 | |||
| 425 | SomethingCache::KeyList lKeys = c.getKeys(); | ||
| 426 | for( SomethingCache::KeyList::iterator i = lKeys.begin(); i; i++ ) | ||
| 427 | { | ||
| 428 | Bu::println(" - %1").arg( *i ); | ||
| 429 | } | ||
| 430 | |||
| 225 | 431 | ||
| 226 | return 0; | 432 | return 0; |
| 227 | } | 433 | } |
diff --git a/src/unstable/uuid.cpp b/src/unstable/uuid.cpp index 06e8c01..a93f713 100644 --- a/src/unstable/uuid.cpp +++ b/src/unstable/uuid.cpp | |||
| @@ -160,15 +160,20 @@ template<> bool Bu::__cmpHashKeys<Bu::Uuid>( const Bu::Uuid &a, const Bu::Uuid & | |||
| 160 | return a == b; | 160 | return a == b; |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, Uuid &u ) | 163 | Bu::ArchiveBase &Bu::operator>>( Bu::ArchiveBase &ar, Bu::Uuid &u ) |
| 164 | { | 164 | { |
| 165 | ar.read( u.data, 16 ); | 165 | ar.read( u.data, 16 ); |
| 166 | return ar; | 166 | return ar; |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, const Uuid &u ) | 169 | Bu::ArchiveBase &Bu::operator<<( Bu::ArchiveBase &ar, const Bu::Uuid &u ) |
| 170 | { | 170 | { |
| 171 | ar.write( u.data, 16 ); | 171 | ar.write( u.data, 16 ); |
| 172 | return ar; | 172 | return ar; |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::Uuid &u ) | ||
| 176 | { | ||
| 177 | return f << u.toString(); | ||
| 178 | } | ||
| 179 | |||
diff --git a/src/unstable/uuid.h b/src/unstable/uuid.h index e7c5f00..35cb69c 100644 --- a/src/unstable/uuid.h +++ b/src/unstable/uuid.h | |||
| @@ -64,8 +64,10 @@ namespace Bu | |||
| 64 | template<> bool __cmpHashKeys<Uuid>( | 64 | template<> bool __cmpHashKeys<Uuid>( |
| 65 | const Uuid &a, const Uuid &b ); | 65 | const Uuid &a, const Uuid &b ); |
| 66 | 66 | ||
| 67 | class Formatter; | ||
| 67 | Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, Uuid &u ); | 68 | Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, Uuid &u ); |
| 68 | Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const Uuid &u ); | 69 | Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const Uuid &u ); |
| 70 | Bu::Formatter &operator<<( Bu::Formatter &f, const Uuid &u ); | ||
| 69 | }; | 71 | }; |
| 70 | 72 | ||
| 71 | #endif | 73 | #endif |
