00001 #ifndef _BOUNDED_CACHE_H_
00002 #define _BOUNDED_CACHE_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <it_dsa/hash_map.h>
00014 #include <it_dsa/list.h>
00015 #include <it_bus/types.h>
00016
00017 namespace IT_Bus
00018 {
00019 template<class Data>
00020 class Evictor
00021 {
00022 public:
00023 virtual void evict(Data data) = 0;
00024 };
00025
00026 template<class Key, class Data, class HashFn, class Equal>
00027 class BoundedCache
00028 {
00029 public:
00030 BoundedCache(
00031 size_t max_sz,
00032 Evictor<Data>* evictor
00033 ) : m_evictor(evictor),
00034 m_max(max_sz)
00035 {
00036
00037 }
00038
00039 ~BoundedCache()
00040 {
00041 if (size() == 0)
00042 {
00043 return;
00044 }
00045
00046 QueueIterator queue_iter = m_queue.begin();
00047
00048 while (queue_iter != m_queue.end())
00049 {
00050 DataKeyPair pair = (*queue_iter);
00051 m_queue.erase(queue_iter++);
00052 MapIterator i = m_map.find(*pair.second);
00053 m_map.erase(i);
00054 }
00055
00056 }
00057
00058 Boolean insert(
00059 const Key& key,
00060 const Data& data
00061 )
00062 {
00063 IT_Pair<MapIterator, IT_Bool> result;
00064 result = m_map.insert(IT_TYPENAME HashMap::value_type(key, data));
00065 if (result.second)
00066 {
00067 DataKeyPair pair(data, &key);
00068 m_queue.push_back(pair);
00069 enforce_max();
00070 }
00071 return result.second;
00072 }
00073
00074 Boolean remove(const Key& key)
00075 {
00076 if (size() == 0)
00077 {
00078 return false;
00079 }
00080
00081 MapIterator i = m_map.find(key);
00082 if (i == m_map.end())
00083 {
00084 return false;
00085 }
00086
00087 m_map.erase(i);
00088
00089 QueueIterator queue_iter = m_queue.begin();
00090
00091 while (queue_iter != m_queue.end())
00092 {
00093 if (*(*queue_iter).second == key)
00094 {
00095 DataKeyPair pair = (*queue_iter);
00096 m_queue.erase(queue_iter);
00097 assert(m_queue.size() == m_map.size());
00098 return true;
00099 }
00100 queue_iter++;
00101 }
00102
00103 assert(m_queue.size() == m_map.size());
00104 return false;
00105 }
00106
00107 Data* find(const Key& key)
00108 {
00109 if (size() == 0)
00110 {
00111 return 0;
00112 }
00113
00114 MapIterator i = m_map.find(key);
00115 if (i == m_map.end())
00116 {
00117 return 0;
00118 }
00119 else
00120 {
00121 QueueIterator queue_iter = m_queue.begin();
00122
00123 while (queue_iter != m_queue.end())
00124 {
00125 if (*(*queue_iter).second == key)
00126 {
00127 DataKeyPair move = (*queue_iter);
00128 m_queue.erase(queue_iter);
00129 m_queue.push_back(move);
00130
00131 assert(m_queue.size() == m_map.size());
00132 return &((*i).second);
00133 }
00134 queue_iter++;
00135 }
00136
00137 assert(0);
00138 return 0;
00139 }
00140 }
00141
00142 const Data* find(const Key& key) const
00143 {
00144 if (size() == 0)
00145 {
00146 return 0;
00147 }
00148
00149 MapIterator i = m_map.find(key);
00150 if (i == m_map.end())
00151 {
00152 return 0;
00153 }
00154 else
00155 {
00156 QueueIterator queue_iter = m_queue.begin();
00157
00158 while (queue_iter != m_queue.end())
00159 {
00160 if ((*queue_iter).second == key)
00161 {
00162 DataKeyPair move = (*queue_iter);
00163 m_queue.erase(queue_iter);
00164 m_queue.push_back(move);
00165
00166 assert(m_queue.size() == m_map.size());
00167 return &((*i).second);
00168 }
00169 queue_iter++;
00170 }
00171
00172 assert(0);
00173 return 0;
00174 }
00175 }
00176
00177
00178 size_t size() const
00179 {
00180 return m_map.size();
00181 }
00182
00183 size_t max() const
00184 {
00185 return m_max;
00186 }
00187
00188 void max(size_t max_sz)
00189 {
00190 if (m_max > max_sz)
00191 {
00192
00193 return;
00194 }
00195
00196 m_max = max_sz;
00197
00198
00199
00200
00201
00202 while (m_map.size() > m_max)
00203 {
00204 enforce_max();
00205 }
00206 }
00207
00208 private:
00209 typedef IT_HashMap<Key, Data, HashFn, Equal> HashMap;
00210 typedef IT_TYPENAME HashMap::iterator MapIterator;
00211 typedef IT_Pair<Data, const Key*> DataKeyPair;
00212 typedef IT_List<DataKeyPair> Queue;
00213 typedef IT_TYPENAME Queue::iterator QueueIterator;
00214
00215 void enforce_max()
00216 {
00217 if (max() == 0)
00218 {
00219 return;
00220 }
00221
00222 if (size() > max())
00223 {
00224 DataKeyPair data = m_queue.front();
00225 m_queue.pop_front();
00226
00227 MapIterator i = m_map.find(*data.second);
00228
00229 m_map.erase(i);
00230 m_evictor->evict(data.first);
00231 }
00232 assert(m_queue.size() == m_map.size());
00233 }
00234
00235
00236 HashMap m_map;
00237 Queue m_queue;
00238 Evictor<Data>* m_evictor;
00239 size_t m_max;
00240
00241
00242 BoundedCache(const BoundedCache&);
00243 IT_Bus::Boolean operator == (const BoundedCache&);
00244 };
00245
00246 }
00247
00248 #endif