Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
cache_adt.h
Go to the documentation of this file.
1/* Copyright (C) 2021 Wildfire Games.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining
4 * a copy of this software and associated documentation files (the
5 * "Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, sublicense, and/or sell copies of the Software, and to
8 * permit persons to whom the Software is furnished to do so, subject to
9 * the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23/*
24 * Customizable cache data structure.
25 */
26
27#ifndef INCLUDED_CACHE_ADT
28#define INCLUDED_CACHE_ADT
29
30#include <cfloat>
31#include <list>
32#include <queue> // std::priority_queue
33#include <unordered_map>
34
35/*
36Cache for items of variable size and value/"cost".
37underlying displacement algorithm is pluggable; default is "Landlord".
38
39template reference:
40Entry provides size, cost, credit and credit_density().
41 rationale:
42 - made a template instead of exposing Cache::Entry because
43 that would drag a lot of stuff out of Cache.
44 - calculates its own density since that entails a Divider functor,
45 which requires storage inside Entry.
46Entries is a collection with iterator and begin()/end() and
47 "static Entry& entry_from_it(iterator)".
48 rationale:
49 - STL map has pair<key, item> as its value_type, so this
50 function would return it->second. however, we want to support
51 other container types (where we'd just return *it).
52Manager is a template parameterized on typename Key and class Entry.
53 its interface is as follows:
54
55 // is the cache empty?
56 bool empty() const;
57
58 // add (key, entry) to cache.
59 void add(const Key& key, const Entry& entry);
60
61 // if the entry identified by <key> is not in cache, return false;
62 // otherwise return true and pass back a pointer to it.
63 bool find(const Key& key, const Entry** pentry) const;
64
65 // remove an entry from cache, which is assumed to exist!
66 // this makes sense because callers will typically first use find() to
67 // return info about the entry; this also checks if present.
68 void remove(const Key& key);
69
70 // mark <entry> as just accessed for purpose of cache management.
71 // it will tend to be kept in cache longer.
72 void on_access(Entry& entry);
73
74 // caller's intent is to remove the least valuable entry.
75 // in implementing this, you have the latitude to "shake loose"
76 // several entries (e.g. because their 'value' is equal).
77 // they must all be push_back-ed into the list; Cache will dole
78 // them out one at a time in FIFO order to callers.
79 //
80 // rationale:
81 // - it is necessary for callers to receive a copy of the
82 // Entry being evicted - e.g. file_cache owns its items and
83 // they must be passed back to allocator when evicted.
84 // - e.g. Landlord can potentially see several entries become
85 // evictable in one call to remove_least_valuable. there are
86 // several ways to deal with this:
87 // 1) generator interface: we return one of { empty, nevermind,
88 // removed, remove-and-call-again }. this greatly complicates
89 // the call site.
90 // 2) return immediately after finding an item to evict.
91 // this changes cache behavior - entries stored at the
92 // beginning would be charged more often (unfair).
93 // resuming charging at the next entry doesn't work - this
94 // would have to be flushed when adding, at which time there
95 // is no provision for returning any items that may be evicted.
96 // 3) return list of all entries "shaken loose". this incurs
97 // frequent mem allocs, which can be alleviated via suballocator.
98 // note: an intrusive linked-list doesn't make sense because
99 // entries to be returned need to be copied anyway (they are
100 // removed from the manager's storage).
101 void remove_least_valuable(std::list<Entry>& entry_list)
102*/
103
104
105//
106// functors to calculate minimum credit density (MCD)
107//
108
109// MCD is required for the Landlord algorithm's evict logic.
110// [Young02] calls it '\delta'.
111
112// scan over all entries and return MCD.
113template<class Entries> float ll_calc_min_credit_density(const Entries& entries)
114{
115 float min_credit_density = FLT_MAX;
116 for(typename Entries::const_iterator it = entries.begin(); it != entries.end(); ++it)
117 {
118 const float credit_density = Entries::entry_from_it(it).credit_density();
119 min_credit_density = std::min(min_credit_density, credit_density);
120 }
121 return min_credit_density;
122}
123
124// note: no warning is given that the MCD entry is being removed!
125// (reduces overhead in remove_least_valuable)
126// these functors must account for that themselves (e.g. by resetting
127// their state directly after returning MCD).
128
129// determine MCD by scanning over all entries.
130// tradeoff: O(N) time complexity, but all notify* calls are no-ops.
131template<class Entry, class Entries>
133{
134public:
135 void notify_added(const Entry&) const {}
136 void notify_decreased(const Entry&) const {}
138 void notify_increased_or_removed(const Entry&) const {}
139 float operator()(const Entries& entries) const
140 {
141 const float mcd = ll_calc_min_credit_density(entries);
142 return mcd;
143 }
144};
145
146// cache previous MCD and update it incrementally (when possible).
147// tradeoff: amortized O(1) time complexity, but notify* calls must
148// perform work whenever something in the cache changes.
149template<class Entry, class Entries>
151{
152public:
154
155 void notify_added(const Entry& entry)
156 {
157 // when adding a new item, the minimum credit density can only
158 // decrease or remain the same; acting as if entry's credit had
159 // been decreased covers both cases.
160 notify_decreased(entry);
161 }
162
163 void notify_decreased(const Entry& entry)
164 {
165 min_credit_density = std::min(min_credit_density, entry.credit_density());
166 }
167
169 {
170 // remember if this entry had the smallest density
171 is_min_entry = feq(min_credit_density, entry.credit_density());
172 }
173
175 {
176 // .. it did and was increased or removed. we must invalidate
177 // MCD and recalculate it next time.
178 if(is_min_entry)
179 {
180 min_valid = false;
181 min_credit_density = -1.0f;
182 }
183 }
184
185 float operator()(const Entries& entries)
186 {
187 if(min_valid)
188 {
189 // the entry that has MCD will be removed anyway by caller;
190 // we need to invalidate here because they don't call
191 // notify_increased_or_removed.
192 min_valid = false;
193 return min_credit_density;
194 }
195
196 // this is somewhat counterintuitive. since we're calculating
197 // MCD directly, why not mark our cached version of it valid
198 // afterwards? reason is that our caller will remove the entry with
199 // MCD, so it'll be invalidated anyway.
200 // instead, our intent is to calculate MCD for the *next time*.
201 const float ret = ll_calc_min_credit_density(entries);
202 min_valid = true;
203 min_credit_density = FLT_MAX;
204 return ret;
205 }
206
207private:
210
211 // temporary flag set by notify_impending_increase_or_remove
213};
214
215
216//
217// Landlord cache management policy: see [Young02].
218//
219
220// in short, each entry has credit initially set to cost. when wanting to
221// remove an item, all are charged according to MCD and their size;
222// entries are evicted if their credit is exhausted. accessing an entry
223// restores "some" of its credit.
224template<typename Key, typename Entry, template<class Entry_, class Entries> class McdCalc = McdCalc_Cached>
226{
227public:
228 bool empty() const
229 {
230 return map.empty();
231 }
232
233 void add(const Key& key, const Entry& entry)
234 {
235 // adapter for add_ (which returns an iterator)
236 (void)add_(key, entry);
237 }
238
239 bool find(const Key& key, const Entry** pentry) const
240 {
241 MapCIt it = map.find(key);
242 if(it == map.end())
243 return false;
244 *pentry = &it->second;
245 return true;
246 }
247
248 void remove(const Key& key)
249 {
250 MapIt it = map.find(key);
251 // note: don't complain if not in the cache: this happens after
252 // writing a file and invalidating its cache entry, which may
253 // or may not exist.
254 if(it != map.end())
255 remove_(it);
256 }
257
258 void on_access(Entry& entry)
259 {
260 mcd_calc.notify_impending_increase_or_remove(entry);
261
262 // Landlord algorithm calls for credit to be reset to anything
263 // between its current value and the cost.
264 const float gain = 0.75f; // restore most credit
265 entry.credit = gain*entry.cost + (1.0f-gain)*entry.credit;
266
267 mcd_calc.notify_increased_or_removed(entry);
268 }
269
270 void remove_least_valuable(std::list<Entry>& entry_list)
271 {
272 // we are required to evict at least one entry. one iteration
273 // ought to suffice, due to definition of min_credit_density and
274 // tolerance; however, we provide for repeating if necessary.
275again:
276
277 // messing with this (e.g. raising if tiny) would result in
278 // different evictions than Landlord_Lazy, which is unacceptable.
279 // nor is doing so necessary: if mcd is tiny, so is credit.
280 const float min_credit_density = mcd_calc(map);
281 ENSURE(min_credit_density > 0.0f);
282
283 for(MapIt it = map.begin(); it != map.end();) // no ++it
284 {
285 Entry& entry = it->second;
286
287 charge(entry, min_credit_density);
288 if(should_evict(entry))
289 {
290 entry_list.push_back(entry);
291
292 // annoying: we have to increment <it> before erasing
293 MapIt it_to_remove = it++;
294 map.erase(it_to_remove);
295 }
296 else
297 {
298 mcd_calc.notify_decreased(entry);
299 ++it;
300 }
301 }
302
303 if(entry_list.empty())
304 goto again;
305 }
306
307protected:
308 class Map : public std::unordered_map<Key, Entry>
309 {
310 public:
311 static Entry& entry_from_it(typename Map::iterator it) { return it->second; }
312 static const Entry& entry_from_it(typename Map::const_iterator it) { return it->second; }
313 };
314 typedef typename Map::iterator MapIt;
315 typedef typename Map::const_iterator MapCIt;
317
318 // add entry and return iterator pointing to it.
319 MapIt add_(const Key& key, const Entry& entry)
320 {
321 typedef std::pair<MapIt, bool> PairIB;
322 typename Map::value_type val = std::make_pair(key, entry);
323 PairIB ret = map.insert(val);
324 ENSURE(ret.second); // must not already be in map
325
326 mcd_calc.notify_added(entry);
327
328 return ret.first;
329 }
330
331 // remove entry (given by iterator) directly.
332 void remove_(MapIt it)
333 {
334 const Entry& entry = it->second;
335 mcd_calc.notify_impending_increase_or_remove(entry);
336 mcd_calc.notify_increased_or_removed(entry);
337 map.erase(it);
338 }
339
340 void charge(Entry& entry, float delta)
341 {
342 entry.credit -= delta * entry.size;
343
344 // don't worry about entry.size being 0 - if so, cost
345 // should also be 0, so credit will already be 0 anyway.
346 }
347
348 // for each entry, 'charge' it (i.e. reduce credit by) delta * its size.
349 // delta is typically MCD (see above); however, several such updates
350 // may be lumped together to save time. Landlord_Lazy does this.
351 void charge_all(float delta)
352 {
353 for(MapIt it = map.begin(); it != map.end(); ++it)
354 {
355 Entry& entry = it->second;
356 entry.credit -= delta * entry.size;
357 if(!should_evict(entry))
358 mcd_calc.notify_decreased(entry);
359 }
360 }
361
362 // is entry's credit exhausted? if so, it should be evicted.
363 bool should_evict(const Entry& entry)
364 {
365 // we need a bit of leeway because density calculations may not
366 // be exact. choose value carefully: must not be high enough to
367 // trigger false positives.
368 return entry.credit < 0.0001f;
369 }
370
371private:
372 McdCalc<Entry, Map> mcd_calc;
373};
374
375// Cache manger policies. (these are partial specializations of Landlord,
376// adapting it to the template params required by Cache)
377template<class Key, class Entry> class Landlord_Naive : public Landlord<Key, Entry, McdCalc_Naive> {};
378template<class Key, class Entry> class Landlord_Cached: public Landlord<Key, Entry, McdCalc_Cached> {};
379
380// variant of Landlord that adds a priority queue to directly determine
381// which entry to evict. this allows lumping several charge operations
382// together and thus reduces iteration over all entries.
383// tradeoff: O(logN) removal (instead of N), but additional O(N) storage.
384template<typename Key, class Entry>
385class Landlord_Lazy : public Landlord_Naive<Key, Entry>
386{
390
391public:
393
394 void add(const Key& key, const Entry& entry)
395 {
396 // we must apply pending_delta now - otherwise, the existing delta
397 // would later be applied to this newly added item (incorrect).
399
400 MapIt it = Parent::add_(key, entry);
401 pri_q.push(it);
402 }
403
404 void remove(const Key& key)
405 {
407
408 // reconstruct pri_q from current map. this is slow (N*logN) and
409 // could definitely be done better, but we don't bother since
410 // remove is a very rare operation (e.g. invalidating entries).
411 while(!pri_q.empty())
412 pri_q.pop();
413 for(MapCIt it = this->map.begin(); it != this->map.end(); ++it)
414 pri_q.push(it);
415 }
416
417 void on_access(Entry& entry)
418 {
419 Parent::on_access(entry);
420
421 // entry's credit was changed. we now need to reshuffle the
422 // pri queue to reflect this.
424 }
425
426 void remove_least_valuable(std::list<Entry>& entry_list)
427 {
428 MapIt least_valuable_it = pri_q.top(); pri_q.pop();
429 Entry& entry = Map::entry_from_it(least_valuable_it);
430
431 entry_list.push_back(entry);
432
433 // add to pending_delta the MCD that would have resulted
434 // if removing least_valuable_it normally.
435 // first, calculate actual credit (i.e. apply pending_delta to
436 // this entry); then add the resulting density to pending_delta.
437 entry.credit -= pending_delta*entry.size;
438 const float credit_density = entry.credit_density();
439 ENSURE(credit_density > 0.0f);
440 pending_delta += credit_density;
441
442 Parent::remove_(least_valuable_it);
443 }
444
445private:
447
448 // sort iterators by credit_density of the Entry they reference.
450 {
451 bool operator()(MapIt it1, MapIt it2) const
452 {
453 return Map::entry_from_it(it1).credit_density() >
454 Map::entry_from_it(it2).credit_density();
455 }
456 };
457 // wrapper on top of priority_queue that allows 'heap re-sift'
458 // (see on_access).
459 // notes:
460 // - greater comparator makes pri_q.top() the one with
461 // LEAST credit_density, which is what we want.
462 // - deriving from an STL container is a bit dirty, but we need this
463 // to get at the underlying data (priority_queue interface is not
464 // very capable).
465 class PriQ: public std::priority_queue<MapIt, std::vector<MapIt>, CD_greater>
466 {
467 public:
469 {
470 // TODO: this is actually N*logN - ouch! that explains high
471 // CPU cost in profile. this is called after only 1 item has
472 // changed, so a logN "sift" operation ought to suffice.
473 // that's not supported by the STL heap functions, so we'd
474 // need a better implementation. pending..
475 std::make_heap(this->c.begin(), this->c.end(), this->comp);
476 }
477 };
479
480 // delta values that have accumulated over several
481 // remove_least_valuable() calls. applied during add().
483
485 {
486 if(pending_delta > 0.0f)
487 {
488 this->charge_all(pending_delta);
489 pending_delta = 0.0f;
490
491 // we've changed entry credit, so the heap order *may* have been
492 // violated; reorder the pri queue. (I don't think so,
493 // due to definition of delta, but we'll play it safe)
495 }
496 }
497};
498
499
500//
501// functor that implements division of first arg by second
502//
503
504// this is used to calculate credit_density(); performance matters
505// because this is called for each entry during each remove operation.
506
507// floating-point division (fairly slow)
509{
510public:
511 Divider_Naive() {} // needed for default CacheEntry ctor
513 float operator()(float val, float divisor) const
514 {
515 return val / divisor;
516 }
517};
518
519// caches reciprocal of divisor and multiplies by that.
520// tradeoff: only 4 clocks (instead of 20), but 4 bytes extra per entry.
522{
523 float recip;
524public:
525 Divider_Recip() {} // needed for default CacheEntry ctor
526 Divider_Recip(float x) { recip = 1.0f / x; }
527 float operator()(float val, float UNUSED(divisor)) const
528 {
529 return val * recip;
530 }
531};
532
533
534// initial implementation for testing purposes; quite inefficient.
535template<typename Key, typename Entry>
536class LRU
537{
538public:
539 bool empty() const
540 {
541 return lru.empty();
542 }
543
544 void add(const Key& key, const Entry& entry)
545 {
546 lru.push_back(KeyAndEntry(key, entry));
547 }
548
549 bool find(const Key& key, const Entry** pentry) const
550 {
551 CIt it = std::find(lru.begin(), lru.end(), KeyAndEntry(key));
552 if(it == lru.end())
553 return false;
554 *pentry = &it->entry;
555 return true;
556 }
557
558 void remove(const Key& key)
559 {
560 lru.remove(KeyAndEntry(key));
561 }
562
563 void on_access(Entry& entry)
564 {
565 for(It it = lru.begin(); it != lru.end(); ++it)
566 {
567 if(&entry == &it->entry)
568 {
569 add(it->key, it->entry);
570 lru.erase(it);
571 return;
572 }
573 }
574 DEBUG_WARN_ERR(ERR::LOGIC); // entry not found in list
575 }
576
577 void remove_least_valuable(std::list<Entry>& entry_list)
578 {
579 entry_list.push_back(lru.front().entry);
580 lru.pop_front();
581 }
582
583private:
585 {
586 KeyAndEntry(const Key& key): key(key) {}
587 KeyAndEntry(const Key& key, const Entry& entry): key(key), entry(entry) {}
588
589 bool operator==(const KeyAndEntry& rhs) const { return key == rhs.key; }
590 bool operator!=(const KeyAndEntry& rhs) const { return !operator==(rhs); }
591
592 Key key;
594 };
595
596 typedef std::list<KeyAndEntry> List;
597 typedef typename List::iterator It;
598 typedef typename List::const_iterator CIt;
600};
601
602
603// this is applicable to all cache management policies and stores all
604// required information. a Divider functor is used to implement
605// division for credit_density.
606template<class Item, class Divider> struct CacheEntry
607{
608 Item item;
609 size_t size;
610 size_t cost;
611 float credit;
612
613 Divider divider;
614
615 // needed for mgr.remove_least_valuable's entry_copy
617 {
618 }
619
620 CacheEntry(const Item& item_, size_t size_, size_t cost_)
621 : item(item_), divider((float)size_)
622 {
623 size = size_;
624 cost = cost_;
625 credit = (float)cost;
626
627 // else divider will fail
628 ENSURE(size != 0);
629 }
630
631 float credit_density() const
632 {
633 return divider(credit, (float)size);
634 }
635};
636
637
638//
639// Cache
640//
641
642template
643<
644typename Key, typename Item,
645// see documentation above for Manager's interface.
646template<typename Key_, class Entry> class Manager = Landlord_Cached,
647class Divider = Divider_Naive
648>
649class Cache
650{
651public:
652 Cache() : mgr() {}
653
654 void add(const Key& key, const Item& item, size_t size, size_t cost)
655 {
656 return mgr.add(key, Entry(item, size, cost));
657 }
658
659 // remove the entry identified by <key>. expected usage is to check
660 // if present and determine size via retrieve(), so no need for
661 // error checking.
662 // useful for invalidating single cache entries.
663 void remove(const Key& key)
664 {
665 mgr.remove(key);
666 }
667
668 // if there is no entry for <key> in the cache, return false.
669 // otherwise, return true and pass back item and (optionally) size.
670 //
671 // if refill_credit (default), the cache manager 'rewards' this entry,
672 // tending to keep it in cache longer. this parameter is not used in
673 // normal operation - it's only for special cases where we need to
674 // make an end run around the cache accounting (e.g. for cache simulator).
675 bool retrieve(const Key& key, Item& item, size_t* psize = 0, bool refill_credit = true)
676 {
677 const Entry* entry;
678 if(!mgr.find(key, &entry))
679 return false;
680
681 item = entry->item;
682 if(psize)
683 *psize = entry->size;
684
685 if(refill_credit)
686 mgr.on_access((Entry&)*entry);
687
688 return true;
689 }
690
691 bool peek(const Key& key, Item& item, size_t* psize = 0)
692 {
693 return retrieve(key, item, psize, false);
694 }
695
696 // toss out the least valuable entry. return false if cache is empty,
697 // otherwise true and (optionally) pass back its item and size.
698 bool remove_least_valuable(Item* pItem = 0, size_t* pSize = 0)
699 {
700 // as an artefact of the cache eviction policy, several entries
701 // may be "shaken loose" by one call to remove_least_valuable.
702 // we cache them in a list to disburden callers (they always get
703 // exactly one).
704 if(entries_awaiting_eviction.empty())
705 {
706 if(empty())
707 return false;
708
709 mgr.remove_least_valuable(entries_awaiting_eviction);
711 }
712
713 const Entry& entry = entries_awaiting_eviction.front();
714 if(pItem)
715 *pItem = entry.item;
716 if(pSize)
717 *pSize = entry.size;
718 entries_awaiting_eviction.pop_front();
719
720 return true;
721 }
722
723 bool empty() const
724 {
725 return mgr.empty();
726 }
727
728private:
730
731 // see note in remove_least_valuable().
733
734 Manager<Key, Entry> mgr;
735};
736
737#endif // #ifndef INCLUDED_CACHE_ADT
uint32_t Entry
Definition: SilhouetteRenderer.cpp:138
float ll_calc_min_credit_density(const Entries &entries)
Definition: cache_adt.h:113
Definition: cache_adt.h:650
Cache()
Definition: cache_adt.h:652
void remove(const Key &key)
Definition: cache_adt.h:663
std::list< Entry > entries_awaiting_eviction
Definition: cache_adt.h:732
CacheEntry< Item, Divider > Entry
Definition: cache_adt.h:729
bool remove_least_valuable(Item *pItem=0, size_t *pSize=0)
Definition: cache_adt.h:698
void add(const Key &key, const Item &item, size_t size, size_t cost)
Definition: cache_adt.h:654
bool empty() const
Definition: cache_adt.h:723
bool peek(const Key &key, Item &item, size_t *psize=0)
Definition: cache_adt.h:691
bool retrieve(const Key &key, Item &item, size_t *psize=0, bool refill_credit=true)
Definition: cache_adt.h:675
Manager< Key, Entry > mgr
Definition: cache_adt.h:734
Definition: cache_adt.h:509
float operator()(float val, float divisor) const
Definition: cache_adt.h:513
Divider_Naive()
Definition: cache_adt.h:511
Divider_Naive(float x)
Definition: cache_adt.h:512
Definition: cache_adt.h:522
Divider_Recip(float x)
Definition: cache_adt.h:526
Divider_Recip()
Definition: cache_adt.h:525
float operator()(float val, float divisor) const
Definition: cache_adt.h:527
float recip
Definition: cache_adt.h:523
Definition: cache_adt.h:537
List::iterator It
Definition: cache_adt.h:597
void on_access(Entry &entry)
Definition: cache_adt.h:563
std::list< KeyAndEntry > List
Definition: cache_adt.h:596
List::const_iterator CIt
Definition: cache_adt.h:598
void add(const Key &key, const Entry &entry)
Definition: cache_adt.h:544
void remove(const Key &key)
Definition: cache_adt.h:558
bool find(const Key &key, const Entry **pentry) const
Definition: cache_adt.h:549
void remove_least_valuable(std::list< Entry > &entry_list)
Definition: cache_adt.h:577
bool empty() const
Definition: cache_adt.h:539
List lru
Definition: cache_adt.h:599
Definition: cache_adt.h:309
static const Entry & entry_from_it(typename Map::const_iterator it)
Definition: cache_adt.h:312
static Entry & entry_from_it(typename Map::iterator it)
Definition: cache_adt.h:311
Definition: cache_adt.h:378
Definition: cache_adt.h:466
void ensure_heap_order()
Definition: cache_adt.h:468
Definition: cache_adt.h:386
Landlord_Naive< Key, Entry >::MapIt MapIt
Definition: cache_adt.h:388
void add(const Key &key, const Entry &entry)
Definition: cache_adt.h:394
void remove_least_valuable(std::list< Entry > &entry_list)
Definition: cache_adt.h:426
void on_access(Entry &entry)
Definition: cache_adt.h:417
Landlord_Naive< Key, Entry > Parent
Definition: cache_adt.h:446
PriQ pri_q
Definition: cache_adt.h:478
Landlord_Naive< Key, Entry >::Map Map
Definition: cache_adt.h:387
void remove(const Key &key)
Definition: cache_adt.h:404
Landlord_Naive< Key, Entry >::MapCIt MapCIt
Definition: cache_adt.h:389
float pending_delta
Definition: cache_adt.h:482
void commit_pending_delta()
Definition: cache_adt.h:484
Landlord_Lazy()
Definition: cache_adt.h:392
Definition: cache_adt.h:377
Definition: cache_adt.h:226
void charge_all(float delta)
Definition: cache_adt.h:351
void remove_least_valuable(std::list< Entry > &entry_list)
Definition: cache_adt.h:270
MapIt add_(const Key &key, const Entry &entry)
Definition: cache_adt.h:319
McdCalc< Entry, Map > mcd_calc
Definition: cache_adt.h:372
void on_access(Entry &entry)
Definition: cache_adt.h:258
void add(const Key &key, const Entry &entry)
Definition: cache_adt.h:233
void remove(const Key &key)
Definition: cache_adt.h:248
void charge(Entry &entry, float delta)
Definition: cache_adt.h:340
Map map
Definition: cache_adt.h:316
bool find(const Key &key, const Entry **pentry) const
Definition: cache_adt.h:239
void remove_(MapIt it)
Definition: cache_adt.h:332
Map::iterator MapIt
Definition: cache_adt.h:314
bool should_evict(const Entry &entry)
Definition: cache_adt.h:363
Map::const_iterator MapCIt
Definition: cache_adt.h:315
bool empty() const
Definition: cache_adt.h:228
Definition: cache_adt.h:151
void notify_decreased(const Entry &entry)
Definition: cache_adt.h:163
float min_credit_density
Definition: cache_adt.h:208
bool is_min_entry
Definition: cache_adt.h:212
void notify_impending_increase_or_remove(const Entry &entry)
Definition: cache_adt.h:168
float operator()(const Entries &entries)
Definition: cache_adt.h:185
void notify_increased_or_removed(const Entry &entry)
Definition: cache_adt.h:174
bool min_valid
Definition: cache_adt.h:209
McdCalc_Cached()
Definition: cache_adt.h:153
void notify_added(const Entry &entry)
Definition: cache_adt.h:155
Definition: cache_adt.h:133
void notify_decreased(const Entry &) const
Definition: cache_adt.h:136
void notify_increased_or_removed(const Entry &) const
Definition: cache_adt.h:138
void notify_impending_increase_or_remove(const Entry &) const
Definition: cache_adt.h:137
void notify_added(const Entry &) const
Definition: cache_adt.h:135
float operator()(const Entries &entries) const
Definition: cache_adt.h:139
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning.
Definition: code_annotation.h:40
#define DEBUG_WARN_ERR(status)
display the error dialog with text corresponding to the given error code.
Definition: debug.h:326
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
Definition: debug.h:277
bool feq(double d1, double d2, double epsilon=0.00001)
are the given floats nearly "equal"?
Definition: lib.h:88
const Status LOGIC
Definition: status.h:411
Definition: cache_adt.h:607
Item item
Definition: cache_adt.h:608
float credit
Definition: cache_adt.h:611
CacheEntry(const Item &item_, size_t size_, size_t cost_)
Definition: cache_adt.h:620
size_t size
Definition: cache_adt.h:609
Divider divider
Definition: cache_adt.h:613
CacheEntry()
Definition: cache_adt.h:616
size_t cost
Definition: cache_adt.h:610
float credit_density() const
Definition: cache_adt.h:631
Definition: cache_adt.h:585
bool operator==(const KeyAndEntry &rhs) const
Definition: cache_adt.h:589
KeyAndEntry(const Key &key)
Definition: cache_adt.h:586
KeyAndEntry(const Key &key, const Entry &entry)
Definition: cache_adt.h:587
Key key
Definition: cache_adt.h:592
bool operator!=(const KeyAndEntry &rhs) const
Definition: cache_adt.h:590
Entry entry
Definition: cache_adt.h:593
Definition: cache_adt.h:450
bool operator()(MapIt it1, MapIt it2) const
Definition: cache_adt.h:451
pthread_key_t key
Definition: wpthread.cpp:140