aboutsummaryrefslogtreecommitdiff
path: root/src/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests')
-rw-r--r--src/tests/cache.cpp218
1 files changed, 212 insertions, 6 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{
58friend class CacheBase<keytype, basetype>; 61friend class CacheBase<keytype, basetype>;
59private: 62private:
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
74public: 78public:
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
106private:
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
79private: 116private:
80 CacheBase<keytype, basetype> *pCache; 117 CacheBase<keytype, basetype> *pCache;
81 mutable keytype kId; 118 mutable keytype kId;
@@ -86,6 +123,7 @@ private:
86template<typename keytype, typename obtype> 123template<typename keytype, typename obtype>
87class CacheBase 124class CacheBase
88{ 125{
126friend class CachePtr<keytype, obtype>;
89public: 127public:
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
98protected: 184protected:
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
103protected: 232protected:
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
239private:
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
270private:
271 typedef Bu::Hash<keytype, CacheEntry *> CacheEntryHash;
272 CacheEntryHash hCacheEntry;
273 Bu::ReadWriteMutex mCacheEntry;
274
109}; 275};
110 276
111template<typename keytype, typename obtype> 277template<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
140protected: 326protected:
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
206private: 398private:
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
413typedef CachePtr<Bu::Uuid, Something> SomethingPtr;
414typedef MyriadCache<Bu::Uuid, Something> SomethingCache;
415
221int main() 416int 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}