GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 37.8% 51 / 0 / 135
Functions: 56.2% 9 / 0 / 16
Branches: 20.6% 14 / 0 / 68

core/SimpleLruCache.h
Line Branch Exec Source
1 #ifndef AVS_SIMPLELRUCACHE_H
2 #define AVS_SIMPLELRUCACHE_H
3
4 #include <list>
5 #include <functional>
6 #include <limits>
7 #include <avs/minmax.h>
8
9 template<typename K, typename V>
10 class SimpleLruCache
11 {
12 public:
13 struct Entry
14 {
15 K key;
16 V value;
17
18 5 Entry(const K& k) :
19 5 key(k)
20 5 {}
21 };
22
23 typedef V value_type;
24 typedef K key_type;
25 typedef typename std::list<Entry>::iterator entry_type;
26
27 typedef std::function<bool(SimpleLruCache*, const Entry&, void*)> EvictEventType;
28
29 private:
30 size_t MinCapacity;
31 size_t MaxCapacity;
32 size_t RequestedCapacity;
33 size_t RealCapacity;
34 std::list<Entry> Cache;
35 std::list<Entry> Pool;
36
37 void* EventUserData;
38 const EvictEventType EvictEvent;
39
40 public:
41 10 SimpleLruCache(size_t capacity, const EvictEventType&& evict, void* evData) :
42 10 MinCapacity(0),
43 10 MaxCapacity(std::numeric_limits<size_t>::max()),
44 10 RequestedCapacity(capacity),
45 10 RealCapacity(capacity),
46 10 EventUserData(evData),
47
2/4
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruGhostEntry>::SimpleLruCache(unsigned long, std::function<bool (SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruGhostEntry>*, SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruGhostEntry>::Entry const&, void*)> const&&, void*):
✓ Branch 5 → 6 taken 5 times.
✗ Branch 5 → 7 not taken.
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruEntry*>::SimpleLruCache(unsigned long, std::function<bool (SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruEntry*>*, SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruEntry*>::Entry const&, void*)> const&&, void*):
✓ Branch 5 → 6 taken 5 times.
✗ Branch 5 → 7 not taken.
10 EvictEvent(evict)
48 {
49 10 }
50
51 size_t size() const
52 {
53 return Cache.size();
54 }
55
56 5 size_t requested_capacity() const
57 {
58 5 return RequestedCapacity;
59 }
60
61 5 size_t capacity() const
62 {
63 5 return RealCapacity;
64 }
65
66 void limits(size_t* min, size_t* max) const
67 {
68 *min = MinCapacity;
69 *max = MaxCapacity;
70 }
71
72 void set_limits(size_t min, size_t max)
73 {
74 MinCapacity = min;
75 MaxCapacity = max;
76 resize(RequestedCapacity);
77 }
78
79 10 V* lookup(const K& key, bool *found, bool lookuponly = false)
80 {
81 // Look for an existing cache entry,
82 // and return it when found
83 10 const entry_type it_end = Cache.end();
84 10 for (
85 10 entry_type it = Cache.begin();
86
2/4
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruGhostEntry>::lookup(unsigned long const&, bool*, bool):
✗ Branch 19 → 5 not taken.
✓ Branch 19 → 20 taken 5 times.
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruEntry*>::lookup(unsigned long const&, bool*, bool):
✗ Branch 19 → 5 not taken.
✓ Branch 19 → 20 taken 5 times.
10 it != it_end;
87 ++it
88 )
89 {
90 if (it->key == key)
91 {
92 // Move found element to the front of the list
93 if (it != Cache.begin())
94 Cache.splice(Cache.begin(), Cache, it);
95
96 *found = true;
97 return &(Cache.front().value);
98 }
99 }
100
101 // Nothing found
102 10 *found = false;
103
104
2/4
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruGhostEntry>::lookup(unsigned long const&, bool*, bool):
✗ Branch 20 → 22 not taken.
✓ Branch 20 → 23 taken 5 times.
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruEntry*>::lookup(unsigned long const&, bool*, bool):
✗ Branch 20 → 22 not taken.
✓ Branch 20 → 23 taken 5 times.
10 if (lookuponly) {
105 return NULL;
106 }
107
108 // Evict an old element if the cache is full
109
2/4
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruGhostEntry>::lookup(unsigned long const&, bool*, bool):
✓ Branch 23 → 24 taken 5 times.
✗ Branch 23 → 40 not taken.
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruEntry*>::lookup(unsigned long const&, bool*, bool):
✓ Branch 23 → 24 taken 5 times.
✗ Branch 23 → 40 not taken.
10 trim();
110
111
2/4
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruGhostEntry>::lookup(unsigned long const&, bool*, bool):
✓ Branch 24 → 25 taken 5 times.
✗ Branch 24 → 37 not taken.
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruEntry*>::lookup(unsigned long const&, bool*, bool):
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 37 taken 5 times.
10 if (RealCapacity != 0)
112 {
113 // See if we can take one from our pool
114
1/4
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruGhostEntry>::lookup(unsigned long const&, bool*, bool):
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 34 taken 5 times.
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruEntry*>::lookup(unsigned long const&, bool*, bool):
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 34 not taken.
5 if (!Pool.empty())
115 {
116 Cache.splice(Cache.begin(), Pool, Pool.begin());
117 Cache.front().key = key;
118 }
119 else
120 {
121
1/4
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruGhostEntry>::lookup(unsigned long const&, bool*, bool):
✓ Branch 34 → 35 taken 5 times.
✗ Branch 34 → 40 not taken.
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruEntry*>::lookup(unsigned long const&, bool*, bool):
✗ Branch 34 → 35 not taken.
✗ Branch 34 → 40 not taken.
5 Cache.emplace_front(key);
122 }
123
124 5 return &(Cache.front().value);
125 }
126
127 // Return NULL-storage if we cannot store anything
128 5 return NULL;
129 }
130
131 void remove(const K& key)
132 {
133 const entry_type it_end = Cache.end();
134 for (
135 entry_type it = Cache.begin();
136 it != it_end;
137 ++it
138 )
139 {
140 if (it->key == key)
141 {
142 Pool.splice(Pool.begin(), Cache, it);
143 break;
144 }
145 }
146 }
147
148 10 void trim()
149 {
150
2/4
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruGhostEntry>::trim():
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 32 taken 5 times.
SimpleLruCache<unsigned long, LruCache<unsigned long, PVideoFrame>::LruEntry*>::trim():
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 32 taken 5 times.
10 if (Cache.size() > RealCapacity)
151 {
152 size_t nItemsToDelete = Cache.size() - RealCapacity;
153 auto it = --Cache.end();
154 for (size_t i = 0; i < nItemsToDelete; ++i)
155 {
156 auto prev_it = it;
157 bool end = (it == Cache.begin());
158 if (!end)
159 {
160 prev_it = it;
161 --prev_it;
162 }
163
164 if (EvictEvent != NULL)
165 {
166 if (EvictEvent(this, *it, EventUserData))
167 {
168 Pool.splice(Pool.begin(), Cache, it);
169 }
170 }
171 else
172 {
173 // TODO: Do we want the consumer to always define EvictItem?
174 Pool.splice(Pool.begin(), Cache, it);
175 }
176
177 if (!end)
178 it = prev_it;
179 }
180 }
181 10 }
182
183 void resize(size_t new_cap)
184 {
185 RequestedCapacity = new_cap;
186 RealCapacity = clamp(RequestedCapacity, MinCapacity, MaxCapacity);
187 trim();
188 }
189 };
190
191 #endif // AVS_SIMPLELRUCACHE_H
192