Main Page   Modules   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages   Examples  

misc/lru.h

Go to the documentation of this file.
00001 #ifndef MISC_LRU_H
00002 #define MISC_LRU_H
00003 
00004 /*
00005 
00006   GLT OpenGL C++ Toolkit (LGPL)
00007   Copyright (C) 2000-2002 Nigel Stewart  
00008 
00009   Email: nigels.com@gmail.com   
00010   WWW:   http://www.nigels.com/glt/
00011 
00012   This library is free software; you can redistribute it and/or
00013   modify it under the terms of the GNU Lesser General Public
00014   License as published by the Free Software Foundation; either
00015   version 2.1 of the License, or (at your option) any later version.
00016 
00017   This library is distributed in the hope that it will be useful,
00018   but WITHOUT ANY WARRANTY; without even the implied warranty of
00019   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020   Lesser General Public License for more details.
00021 
00022   You should have received a copy of the GNU Lesser General Public
00023   License along with this library; if not, write to the Free Software
00024   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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         // Check that container is not empty
00131         assert(size());
00132 
00133         // Check that the item is not already inserted
00134         assert(!find(first,false));
00135 
00136         // Take the least recently used (LRU) item in the list
00137         typename List::iterator n = _list.end();
00138         --n;
00139 
00140         // Move it to front of list
00141         _list.splice(_list.begin(),_list,n);
00142 
00143         // Remove it from index
00144         _index.erase(n->first);
00145 
00146         // Replace with current data
00147         n->first = first;
00148 
00149         // Update index
00150         _index[first] = n;
00151 
00152         // Return second 
00153         return n->second;
00154     }
00155 
00157     const T2 &insert(const T1 &first,const T2 &second)
00158     {
00159         // Check that the item is not already inserted
00160         assert(!find(first,false));
00161 
00162         // Insert into list
00163         _list.push_front(make_pair(first,second));
00164 
00165         // Iterator
00166         typename List::iterator n = _list.begin();
00167 
00168         // Insert into balanced tree index
00169         _index[first] = n;
00170 
00171         // Return second 
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             // Move node to front of list, if necessary
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 

Generated on Tue Nov 5 11:11:05 2002 for GLT by doxygen1.2.18