diff options
-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 |