6 # include <tpl_dnode.H>
7 # include <tpl_lhash.H>
40 template <
class Key,
class Data>
47 friend class Cache<Key, Data>;
55 bool is_in_hash_table;
57 void lock() Exception_Prototypes(std::runtime_error)
60 throw std::runtime_error(
"Cache_Entry is already locked");
65 void unlock() Exception_Prototypes(std::runtime_error)
68 throw std::runtime_error(
"Cache_Entry is not locked");
73 Dlink* link_lru() {
return &dlink_lru; }
75 Dlink* link_inside() {
return &dlink_inside; }
81 data(d), locked(
false), is_in_hash_table(
false)
86 Cache_Entry() : locked(
false), is_in_hash_table(
false)
91 Data & get_data() {
return data; }
93 const bool & is_locked()
const {
return locked; }
95 const bool & is_in_table()
const {
return is_in_hash_table; }
97 static Cache_Entry * convert_to_cache_entry(Data * data_ptr)
116 const size_t & get_num_entries()
const
118 I(hash_table.
size() <= cache_size);
120 return hash_table.
size();
136 Chunk_Descriptor chunk_list;
144 void insert_entry_to_lru_list(Cache_Entry * cache_entry)
147 lru_list.
insert(cache_entry->link_lru());
150 void remove_entry_from_lru_list(Cache_Entry * cache_entry)
153 cache_entry->link_lru()->del();
156 void insert_entry_to_locked_list(Cache_Entry * cache_entry)
159 locked_list.
insert(cache_entry->link_lru());
162 void remove_entry_from_locked_list(Cache_Entry * cache_entry)
165 cache_entry->link_lru()->del();
168 void move_to_inside_front(Cache_Entry * cache_entry)
170 cache_entry->link_inside()->del();
171 inside_list.
insert(cache_entry->link_inside());
174 void move_to_lru_front(Cache_Entry * cache_entry)
176 cache_entry->link_lru()->del();
177 lru_list.
insert(cache_entry->link_lru());
180 void move_to_lru_rear(Cache_Entry * cache_entry)
182 cache_entry->link_lru()->del();
183 lru_list.
append(cache_entry->link_lru());
186 void do_mru(Cache_Entry * cache_entry)
188 move_to_lru_front(cache_entry);
191 void do_lru(Cache_Entry * cache_entry)
193 move_to_lru_rear(cache_entry);
199 void remove_entry_from_hash_table(Cache_Entry * cache_entry)
201 I(not cache_entry->is_locked());
203 cache_entry->link_inside()->del();
205 hash_table.
remove(cache_entry);
206 cache_entry->is_in_hash_table =
false;
215 Cache_Entry * get_lru_entry()
217 I(hash_table.
size() <= cache_size);
220 throw std::bad_alloc ();
223 Cache_Entry * cache_entry = dlink_lru_to_Cache_Entry(lru_entry_link);
225 I(not cache_entry->is_locked());
227 if (cache_entry->is_in_hash_table)
229 I(hash_table.
search(cache_entry->get_key()) == cache_entry);
230 remove_entry_from_hash_table(cache_entry);
238 Cache_Entry * insert_pair(
const Key & key,
const Data & data)
240 Cache_Entry *cache_entry = get_lru_entry();
242 cache_entry->get_key() = key;
243 cache_entry->get_data() = data;
245 inside_list.
insert(cache_entry->link_inside());
247 hash_table.
insert(cache_entry);
248 cache_entry->is_in_hash_table =
true;
255 Cache(
size_t (*hash_fct)(
const Key&),
const size_t & size) :
256 hash_table(hash_fct, size, false),
257 cache_size(hash_table.capacity()), num_lru(0), num_locked(0)
262 Cache_Entry * entries_array =
new Cache_Entry [cache_size];
266 std::unique_ptr<Chunk_Descriptor>
267 chunk_descriptor (
new Chunk_Descriptor (entries_array));
269 chunk_list.
insert(chunk_descriptor.get());
271 for (
int i = 0; i < cache_size; i++)
272 insert_entry_to_lru_list(&entries_array[i]);
274 chunk_descriptor.release();
278 delete [] entries_array;
285 I(hash_table.
size() <= cache_size);
289 Chunk_Descriptor * current_chunk = chunk_list.
remove_next();
291 delete [] current_chunk->
get_data();
292 delete current_chunk;
296 Cache_Entry *
search(
const Key & key)
298 I(hash_table.
size() <= cache_size);
300 Cache_Entry * cache_entry =
301 static_cast<Cache_Entry*
>(hash_table.
search(key));
303 if (cache_entry != NULL)
306 move_to_inside_front(cache_entry);
314 Cache_Entry * search_next(Cache_Entry * cache_entry)
316 Cache_Entry *next_entry =
317 static_cast<Cache_Entry*
>(hash_table.
search_next(cache_entry));
319 if (next_entry != NULL)
322 move_to_inside_front(cache_entry);
328 Cache_Entry * insert(
const Key& key,
const Data& data)
329 Exception_Prototypes (std::bad_alloc)
331 I(hash_table.
size() <= cache_size);
333 return insert_pair(key, data);
336 void lock_entry(Cache_Entry * cache_entry)
337 Exception_Prototypes(std::runtime_error)
339 I(num_locked < get_num_entries());
341 I(hash_table.
search(cache_entry->get_key()) == cache_entry);
342 I(cache_entry->is_in_hash_table);
344 if (cache_entry->is_locked())
345 throw std::runtime_error(
"Cache_Entry is already locked");
347 remove_entry_from_lru_list(cache_entry);
348 insert_entry_to_locked_list(cache_entry);
353 void unlock_entry(Cache_Entry * cache_entry)
354 Exception_Prototypes(std::runtime_error)
356 I(hash_table.
search(cache_entry->get_key()) == cache_entry);
357 I(cache_entry->is_in_hash_table);
358 I(num_locked <= get_num_entries());
360 if (not cache_entry->is_locked())
361 throw std::runtime_error(
"Cache_Entry is not locked");
363 remove_entry_from_locked_list(cache_entry);
364 insert_entry_to_lru_list(cache_entry);
366 cache_entry->unlock();
369 void remove(Cache_Entry * cache_entry)
370 Exception_Prototypes(std::runtime_error)
372 I(hash_table.
search(cache_entry->get_key()) == cache_entry);
374 if (cache_entry->is_locked())
375 throw std::runtime_error(
"Cache_Entry is already locked");
377 remove_entry_from_hash_table(cache_entry);
380 void expand(
const size_t & plus_size)
381 Exception_Prototypes(std::range_error, std::bad_alloc)
383 I(hash_table.
size() <= cache_size);
386 throw std::range_error (
"bad plus_size");
388 const size_t new_cache_size = cache_size + plus_size;
390 Cache_Entry * entries_array =
new Cache_Entry [plus_size];
394 std::unique_ptr<Chunk_Descriptor>
395 chunk_descriptor (
new Chunk_Descriptor (entries_array));
397 ID(
long old_num_items = hash_table.
size());
399 hash_table.
resize(13*(new_cache_size)/10);
401 I(old_num_items == hash_table.
size());
403 for (
int i = 0; i < plus_size; i++)
404 insert_entry_to_lru_list(&entries_array[i]);
406 chunk_list.
insert(chunk_descriptor.release());
408 cache_size = new_cache_size;
412 delete [] entries_array;
417 const size_t & capacity()
const {
return cache_size; }
419 const size_t & size()
const {
return hash_table.
size(); }
421 const size_t & get_num_locked()
const {
return num_locked; }
423 const size_t & get_num_busy_slots()
const
440 I(ret_val->is_in_table());
449 # endif // TPL_CACHE_H
const size_t & size() const
Retorna el número de elementos que contiene la tabla.
Definition: tpl_lhash.H:286
Bucket * insert(Bucket *bucket)
Definition: tpl_lhash.H:160
#define LINKNAME_TO_TYPE(type_name, link_name)
Definition: dlink.H:741
Definition: tpl_cache.H:428
Iterador sobre enlaces.
Definition: dlink.H:437
Dnode< T > * remove_next()
Elimina sucesor a this y retorna su dirección.
Definition: tpl_dnode.H:37
Itor1 search(Itor1 beg, const Itor1 &end, Itor2 searchBeg, const Itor2 &searchEnd, BinaryPredicate op=BinaryPredicate())
Definition: ahAlgo.H:327
Definition: tpl_cache.H:45
Bucket * search(const Key &key) const
Definition: tpl_lhash.H:182
Dlink *& get_prev()
Retorna enlace antes de this.
Definition: dlink.H:189
Definition: tpl_lhash.H:531
Bucket * search_next(Bucket *bucket) const
Definition: tpl_lhash.H:259
size_t resize(size_t new_size)
Definition: tpl_lhash.H:222
const size_t & get_num_busy_slots() const
Retorna la cantidad de entradas del arreglo que están ocupadas.
Definition: tpl_lhash.H:289
void append(Dlink *node)
Definition: dlink.H:166
Dlink * get_current() const
Retorna dirección de nodo actual.
Definition: dlink.H:564
Bucket * remove(Bucket *bucket)
Definition: tpl_lhash.H:209
bool is_empty() const
retorna true si this está vacía
Definition: dlink.H:127
Iterator()
Constructor por omisión.
Definition: dlink.H:492
Definition: tpl_cache.H:41
void insert(Dlink *node)
Definition: dlink.H:140
T & get_data()
Retorna referencia a dato contenido en el nodo.
Definition: tpl_dnode.H:126