00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __UT_ThreadSafeCache__
00021 #define __UT_ThreadSafeCache__
00022
00023 #include "UT_API.h"
00024 #include <SYS/SYS_Types.h>
00025 #include <SYS/SYS_AtomicInt.h>
00026 #include <SYS/SYS_AtomicIntImpl.h>
00027 #include "UT_LockUtil.h"
00028
00029
00030
00031
00032 template <class Lock>
00033 class UT_API UT_ThreadSafeCache {
00034 public:
00035
00036
00037 class UT_CacheItem
00038 {
00039 public:
00040 UT_CacheItem()
00041 : myPrev(0), myNext(0), myMemory(0)
00042 , myRefCount(0), myTimeStamp(0)
00043 , myAllocated(false) {}
00044 virtual ~UT_CacheItem() {}
00045
00046 protected:
00047
00048
00049 virtual int64 allocate(void *parms) = 0;
00050
00051
00052 virtual void deallocate() = 0;
00053
00054
00055 int64 getMemoryUsage() const { return myMemory; }
00056
00057 private:
00058 int getRefCount() const { return myRefCount; }
00059 void incRefCount() { myRefCount.add(1); }
00060 void decRefCount() { myRefCount.add(-1); }
00061
00062 bool isInCache() const { return myNext; }
00063
00064 private:
00065 UT_CacheItem *myPrev;
00066 UT_CacheItem *myNext;
00067 int64 myMemory;
00068 SYS_AtomicInt32 myRefCount;
00069 int myTimeStamp;
00070 bool myAllocated;
00071
00072 friend class UT_ThreadSafeCache;
00073 };
00074
00075 public:
00076
00077
00078
00079
00080
00081
00082 UT_ThreadSafeCache(bool destroy = true, bool fastaccess = true);
00083 ~UT_ThreadSafeCache();
00084
00085
00086 void setMaxMemory(int size_mb);
00087
00088
00089
00090 int64 getMemoryUsage() const { return myMemoryUsed; }
00091
00092
00093
00094
00095
00096
00097 void access(UT_CacheItem *item,
00098 bool lock = true, void *parms = 0);
00099
00100
00101
00102 void release(UT_CacheItem *item);
00103
00104
00105 void free(UT_CacheItem *item);
00106
00107
00108 void freeAll();
00109
00110 private:
00111 void addToCache(UT_CacheItem *item);
00112 void removeFromCache(UT_CacheItem *item);
00113 void allocateItem(UT_CacheItem *item, void *parms)
00114 {
00115 if (!item->myAllocated)
00116 {
00117 int handle = myObjLock.lock(item);
00118 if (!item->myAllocated)
00119 {
00120 item->myMemory = item->allocate(parms);
00121 item->myAllocated = true;
00122 }
00123 myObjLock.unlock(item, handle);
00124 }
00125 }
00126
00127
00128
00129 bool isNearHead(const UT_CacheItem *item) const
00130 { return myHeadTime - item->myTimeStamp <=
00131 myQuarterEntries; }
00132
00133 private:
00134 UT_ObjLockType<Lock> myObjLock;
00135 Lock myThreadLock;
00136 int64 myMemoryLimit;
00137 int64 myMemoryLowWater;
00138 int64 myMemoryUsed;
00139 UT_CacheItem *myHead;
00140 int myEntries;
00141 int myQuarterEntries;
00142 int myHeadTime;
00143 bool myDestroy;
00144 bool myFastAccess;
00145 };
00146
00147 #endif