00001 #ifndef Impala_Util_Cache_h
00002 #define Impala_Util_Cache_h
00003
00004 #include <cstddef>
00005 #include <deque>
00006 #include <iostream>
00007
00008 namespace Impala
00009 {
00010 namespace Util
00011 {
00012
00013
00014 template<class IdxT, class ElemT>
00015 class Cache
00016 {
00017 public:
00018 Cache(int maxCacheSize = 0, bool elemIsPointer = true)
00019 {
00020 mMaxCacheSize = maxCacheSize;
00021 mElemIsPointer = elemIsPointer;
00022 }
00023
00024 virtual
00025 ~Cache()
00026 {
00027 Clear();
00028 }
00029
00030
00031 void
00032 SetSize(int maxCacheSize)
00033 {
00034 mMaxCacheSize = maxCacheSize;
00035 }
00036
00037 void
00038 AddElement(IdxT idx, ElemT elem)
00039 {
00040 if (mMaxCacheSize == 0)
00041 return;
00042 ILOG_DEBUG("add: pushing to front");
00043 mQueue.push_front(CacheElem<IdxT, ElemT>(idx, elem));
00044 if (mQueue.size() > mMaxCacheSize)
00045 PopBack();
00046 }
00047
00048 bool
00049 GetElement(IdxT idx, ElemT& elem)
00050 {
00051 for (CacheIterator i=mQueue.begin() ; i!=mQueue.end() ; ++i)
00052 {
00053 if ((*i).mIdx == idx)
00054 {
00055 elem = (*i).mElem;
00056 mQueue.erase(i);
00057 AddElement(idx, elem);
00058 ILOG_DEBUG("get: found elem @ " << idx);
00059 return true;
00060 }
00061 }
00062 ILOG_DEBUG("get: elem @ " << idx << " not found");
00063 return false;
00064 }
00065
00066 void
00067 RemoveElement(IdxT idx)
00068 {
00069 for (CacheIterator i=mQueue.begin() ; i!=mQueue.end() ; ++i)
00070 {
00071 if ((*i).mIdx == idx)
00072 {
00073 ElemT elem = (*i).mElem;
00074 if (mElemIsPointer && elem)
00075 delete elem;
00076 mQueue.erase(i);
00077 return;
00078 }
00079 }
00080 ILOG_INFO("remove: elem @ " << idx << " not found");
00081 }
00082
00083 void
00084 Dump(String name) const
00085 {
00086 std::ostringstream oss;
00087 oss << name << "Cache::Dump start" << std::endl;
00088 for (CacheConstIterator i=mQueue.begin() ; i!=mQueue.end() ; ++i)
00089 {
00090 oss << (*i).mIdx << " = " << (*i).mElem << std::endl;
00091 }
00092 oss << "Cache::Dump end" << std::endl;
00093 ILOG_INFO(oss.str());
00094 }
00095
00096 void
00097 Clear()
00098 {
00099 if (mElemIsPointer)
00100 {
00101 while(!Empty())
00102 PopBack();
00103 }
00104 else
00105 mQueue.clear();
00106 }
00107
00108 bool
00109 Empty()
00110 {
00111 return mQueue.empty();
00112 }
00113
00114 private:
00115
00116 void
00117 PopBack()
00118 {
00119 if (mElemIsPointer)
00120 {
00121 ElemT e = mQueue.back().mElem;
00122 if (e)
00123 {
00124 delete e;
00125 }
00126 }
00127 mQueue.pop_back();
00128 }
00129
00130 template<class CeIdxT, class CeElemT>
00131 class CacheElem
00132 {
00133 public:
00134
00135 CacheElem()
00136 {
00137 }
00138
00139 CacheElem(CeIdxT idx, CeElemT elem) : mIdx(idx), mElem(elem)
00140 {
00141 }
00142
00143 CeIdxT mIdx;
00144 CeElemT mElem;
00145 };
00146
00147 typedef std::deque< CacheElem<IdxT, ElemT> > CacheQueue;
00148 typedef typename CacheQueue::iterator CacheIterator;
00149 typedef typename CacheQueue::const_iterator CacheConstIterator;
00150
00151 Cache(const Cache&)
00152 {
00153 }
00154
00155 Cache&
00156 operator=(const Cache&);
00157
00158 CacheQueue mQueue;
00159 int mMaxCacheSize;
00160 bool mElemIsPointer;
00161 ILOG_VAR_DECL;
00162 };
00163
00164
00165
00166 ILOG_VAR_INIT_TEMPL_2(Cache,IdxT,ElemT,Impala.Util);
00167
00168 }
00169 }
00170
00171 #endif