00001 #ifndef MISC_LRU_H
00002 #define MISC_LRU_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00033 #include <glt/config.h>
00034
00035 #ifdef GLT_WIN32
00036 #pragma warning(disable : 4786)
00037 #endif
00038
00039 #include <cassert>
00040 #include <list>
00041 #include <map>
00042
00043 #if defined(_STLP_MAP) || defined(__SGI_STL_MAP)
00044 #include <hash_map>
00045 using namespace std;
00046 #define USE_HASH_MAP
00047 #else
00048 #if defined(_CPP_MAP)
00049 #include <ext/hash_map>
00050 using namespace __gnu_cxx;
00051 #define USE_HASH_MAP
00052 #endif
00053 #endif
00054
00060 template<class T1,class T2>
00061 class lru
00062 {
00063 public:
00064
00065 typedef std::list< std::pair<T1,T2> > List;
00066
00067 #ifdef USE_HASH_MAP
00068 typedef hash_map<T1,typename List::iterator> Map;
00069 #else
00070 typedef std::map<T1,typename List::iterator> Map;
00071 #endif
00072
00074 lru()
00075 {
00076 }
00077
00079 ~lru()
00080 {
00081 clear();
00082 }
00083
00085 const uint32 size() const
00086 {
00087 return _list.size();
00088 }
00089
00091 const T2 &front() const
00092 {
00093 assert(size());
00094 return _list.front().second;
00095 }
00096
00098 const T2 &back() const
00099 {
00100 assert(size());
00101 return _list.back().second;
00102 }
00103
00105 const T2 pop_front()
00106 {
00107 const T1 id = _list.front().first;
00108 _index.erase(id);
00109
00110 const T2 tmp = _list.front().second;
00111 _list.erase(_list.begin());
00112 return tmp;
00113 }
00114
00116 const T2 pop_back()
00117 {
00118 const T1 id = _list.back().first;
00119 _index.erase(id);
00120
00121 const T2 tmp = _list.back().second;
00122 _list.erase(--_list.end());
00123
00124 return tmp;
00125 }
00126
00128 T2 &insert(const T1 &first)
00129 {
00130
00131 assert(size());
00132
00133
00134 assert(!find(first,false));
00135
00136
00137 typename List::iterator n = _list.end();
00138 --n;
00139
00140
00141 _list.splice(_list.begin(),_list,n);
00142
00143
00144 _index.erase(n->first);
00145
00146
00147 n->first = first;
00148
00149
00150 _index[first] = n;
00151
00152
00153 return n->second;
00154 }
00155
00157 const T2 &insert(const T1 &first,const T2 &second)
00158 {
00159
00160 assert(!find(first,false));
00161
00162
00163 _list.push_front(make_pair(first,second));
00164
00165
00166 typename List::iterator n = _list.begin();
00167
00168
00169 _index[first] = n;
00170
00171
00172 return n->second;
00173 }
00174
00176 T2 *find(const T1 &first,bool touch = true)
00177 {
00178 typename Map::iterator i = _index.find(first);
00179
00180 if (i==_index.end())
00181 return NULL;
00182 else
00183 {
00184
00185 if (touch)
00186 {
00187 typename List::iterator n = i->second;
00188 _list.splice(_list.begin(),_list,n);
00189 return &(_list.front().second);
00190 }
00191 else
00192 return &(i->second->second);
00193 }
00194 }
00195
00197 const T2 &operator[](const uint32 n) const
00198 {
00199 assert(_list.size());
00200
00201 typename List::const_iterator i = _list.begin();
00202 for (uint32 j=0; j<n-1; j++,i++)
00203 if (i==_list.end())
00204 return _list.back().second;
00205
00206 return i->second;
00207 }
00208
00210 void clear()
00211 {
00212 _index.clear();
00213 _list.clear();
00214 }
00215
00216 private:
00217
00218 List _list;
00219 Map _index;
00220 };
00221
00222 #endif
00223