00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef __UT_LimitedCache__
00019 #define __UT_LimitedCache__
00020
00021 #include "UT_API.h"
00022 #include "UT_Cache.h"
00023 #include "UT_SpinLock.h"
00024 #include "UT_Lock.h"
00025 #include "UT_RefArray.h"
00026 #include "UT_ThreadSafeCache.h"
00027 #include "UT_ConcurrentHashMap.h"
00028 #include "UT_String.h"
00029 #include "UT_SharedPtr.h"
00030
00031
00032 typedef UT_ThreadSafeCache<UT_RecursiveSpinLock> UT_LimitedLRUCache;
00033
00034
00035
00036
00037
00038
00039 class UT_API UT_LimitedCacheKey : public UT_LimitedLRUCache::UT_CacheItem
00040 {
00041 public:
00042 UT_LimitedCacheKey();
00043 virtual ~UT_LimitedCacheKey();
00044
00045
00046 virtual UT_LimitedCacheKey *duplicate() const = 0;
00047
00048
00049 virtual unsigned getHash() const = 0;
00050
00051
00052 virtual bool isEqual(const UT_LimitedCacheKey &key) const = 0;
00053
00054
00055
00056
00057
00058 virtual int64 getTotalMemory() const = 0;
00059
00060
00061
00062 virtual int64 allocate(void *)
00063 { return getTotalMemory(); }
00064 virtual void deallocate(void *cache);
00065
00066 };
00067 typedef UT_SharedPtr<UT_LimitedCacheKey> UT_LimitedCacheKeyHandle;
00068
00069
00070
00071 class UT_API UT_LimitedCacheItem {
00072 public:
00073 UT_LimitedCacheItem();
00074 virtual ~UT_LimitedCacheItem();
00075 };
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 class UT_API UT_LimitedCache : public UT_Cache
00134 {
00135 public:
00136 UT_LimitedCache(const char *cache_name,
00137 int64 size_in_mb=32);
00138 ~UT_LimitedCache();
00139
00140
00141
00142
00143
00144 class Lookup {
00145 public:
00146 Lookup()
00147 : myCache(NULL)
00148 , myKey(NULL)
00149 , myItem(NULL)
00150 { }
00151
00152 Lookup(const Lookup &src)
00153 : myCache(src.myCache)
00154 , myKey(src.myKey)
00155 , myItem(src.myItem)
00156 {
00157 access();
00158 }
00159 ~Lookup()
00160 {
00161 release();
00162 }
00163
00164 const Lookup &operator=(const Lookup &src)
00165 {
00166 if (this != &src)
00167 {
00168
00169 const_cast<Lookup &>(src).access();
00170
00171 release();
00172 myCache = src.myCache;
00173 myKey = src.myKey;
00174 myItem = src.myItem;
00175 }
00176 return *this;
00177 }
00178
00179
00180 bool isValid() const { return myKey; }
00181 const UT_LimitedCacheKey *getKey() const { return myKey; }
00182 UT_LimitedCacheItem *getItem() const { return myItem; }
00183
00184
00185
00186
00187
00188
00189 void clear() { release(); }
00190 private:
00191 Lookup(UT_LimitedCache *cache,
00192 UT_LimitedCacheKey *key,
00193 UT_LimitedCacheItem *item)
00194 : myCache(cache)
00195 , myKey(key)
00196 , myItem(item)
00197 {
00198
00199
00200 }
00201 void access()
00202 {
00203 if (myCache && myKey)
00204 myCache->referenceItem(myKey);
00205 }
00206 void release()
00207 {
00208 if (myCache && myKey)
00209 {
00210 myCache->unreferenceItem(myKey);
00211 myCache = NULL;
00212 myKey = NULL;
00213 myItem = NULL;
00214 }
00215 }
00216 UT_LimitedCacheKey *myKey;
00217 UT_LimitedCache *myCache;
00218 UT_LimitedCacheItem *myItem;
00219 friend class UT_LimitedCache;
00220 };
00221
00222
00223
00224 Lookup operator()(const UT_LimitedCacheKey &key)
00225 { return findItem(key); }
00226 Lookup operator[](const UT_LimitedCacheKey &key)
00227 { return findItem(key); }
00228
00229
00230
00231 int64 entries() const { return myTable.size(); }
00232
00233
00234 int64 lru_entries() const { return myLRUCache.entries(); }
00235
00236
00237
00238 void clearCache();
00239
00240
00241
00242 Lookup findItem(const UT_LimitedCacheKey &key);
00243
00244
00245
00246
00247
00248
00249 Lookup addItem(const UT_LimitedCacheKey &key,
00250 UT_LimitedCacheItem *item);
00251
00252
00253
00254 void deallocateItem(const UT_LimitedCacheKey &key);
00255
00256
00257
00258 virtual const char *utGetCacheName() const
00259 { return myName; }
00260 virtual int64 utGetCurrentSize()
00261 { return myLRUCache.getMemoryUsage(); }
00262 virtual bool utHasMaxSize() const
00263 { return true; }
00264 virtual int64 utGetMaxSize()
00265 { return myLRUCache.getMaxMemoryBytes(); }
00266 virtual void utSetMaxSize(int64 bytes)
00267 { myLRUCache.setMaxMemoryBytes(bytes); }
00268 virtual int64 utReduceCacheSizeBy(int64 amount)
00269 {
00270 int64 used = myLRUCache.getMemoryUsage();
00271 myLRUCache.pruneItems(used - amount);
00272 return used - myLRUCache.getMemoryUsage();
00273 }
00274
00275
00276
00277 void dumpCache() const;
00278
00279 protected:
00280
00281
00282 class ut_KeyCompare {
00283 public:
00284 static size_t hash(const UT_LimitedCacheKey *a)
00285 { return (size_t)a->getHash(); }
00286 static bool equal(const UT_LimitedCacheKey *a,
00287 const UT_LimitedCacheKey *b)
00288 { return a->isEqual(*b); }
00289 };
00290 typedef UT_ConcurrentHashMap<UT_LimitedCacheKey *,
00291 UT_LimitedCacheItem *,
00292 ut_KeyCompare> ut_StorageMap_t;
00293 class ut_StorageTable
00294 : public ut_StorageMap_t
00295 {
00296 public:
00297 static int64 getMemoryUsage() { return sizeof(ut_StorageTable); }
00298 };
00299
00300
00301 public:
00302
00303
00304
00305
00306 typedef ut_StorageMap_t::const_iterator unsafe_traverser;
00307 unsafe_traverser unsafe_begin() const { return myTable.begin(); }
00308 unsafe_traverser unsafe_end() const { return myTable.end(); }
00309
00310
00311 private:
00312 void setMRU(UT_LimitedCacheKey *key);
00313 void referenceItem(UT_LimitedCacheKey *key);
00314 void unreferenceItem(UT_LimitedCacheKey *key);
00315 void destroyItem(const UT_LimitedCacheKey *key, bool del_from_lru);
00316
00317 UT_LimitedLRUCache myLRUCache;
00318 ut_StorageTable myTable;
00319 UT_String myName;
00320
00321 friend class Lookup;
00322 };
00323
00324 #endif