Skip to content

Commit 91dc3af

Browse files
committed
Merge branch 'resizable_cache'
2 parents d04acd2 + f207140 commit 91dc3af

File tree

1 file changed

+101
-11
lines changed

1 file changed

+101
-11
lines changed

21_LRUCacheUnitTest/main.cpp

Lines changed: 101 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class LRUCacheTestApp final : public nbl::application_templates::MonoSystemMonoL
3333
inline TextureReference& operator=(uint64_t semamphoreVal) { lastUsedSemaphoreValue = semamphoreVal; return *this; }
3434
};
3535

36-
using TextureLRUCache = core::LRUCache<uint32_t, TextureReference>;
36+
using TextureLRUCache = core::ResizableLRUCache<uint32_t, TextureReference>;
3737

3838
// we stuff all our work here because its a "single shot" app
3939
bool onAppInitialized(smart_refctd_ptr<ISystem>&& system) override
@@ -44,12 +44,18 @@ class LRUCacheTestApp final : public nbl::application_templates::MonoSystemMonoL
4444

4545
m_logger->log("LRU cache unit test");
4646
m_logger->log("Testing large cache...");
47-
LRUCache<int, char> hugeCache(50000000u);
47+
ResizableLRUCache<int, char> hugeCache(50000000u);
4848
hugeCache.insert(0, '0');
4949
hugeCache.print(m_logger);
5050

51-
52-
LRUCache<int, char> cache(5u);
51+
// Use this to ensure the disposal function is properly called on every element of the first cache
52+
ResizableLRUCache<int, char>::disposal_func_t df([&](std::pair<int, char> a)
53+
{
54+
std::ostringstream tmp;
55+
tmp << "Disposal function called on element (" << a.first << ", " << a.second << ")";
56+
m_logger->log(tmp.str());
57+
});
58+
ResizableLRUCache<int, char> cache(5u, std::move(df));
5359

5460
m_logger->log("Testing insert with const key, const val...");
5561
//const, const
@@ -80,8 +86,11 @@ class LRUCacheTestApp final : public nbl::application_templates::MonoSystemMonoL
8086
//non const, const
8187
int i = 0;
8288
cache.insert(++i, '1');
89+
assert(cache.getState() == "{12, e}, {10, c}, {11, d}, {13, f}, {1, 1}");
8390
cache.insert(++i, '2');
91+
assert(cache.getState() == "{10, c}, {11, d}, {13, f}, {1, 1}, {2, 2}");
8492
cache.insert(++i, '3');
93+
assert(cache.getState() == "{11, d}, {13, f}, {1, 1}, {2, 2}, {3, 3}");
8594
returned = *(cache.get(1));
8695
assert(returned == '1');
8796

@@ -111,7 +120,17 @@ class LRUCacheTestApp final : public nbl::application_templates::MonoSystemMonoL
111120
auto peekedNullptr = cache.peek(5);
112121
assert(peekedNullptr == nullptr);
113122

114-
core::LRUCache<int, std::string> cache2(5u);
123+
// Try clearing the cache
124+
m_logger->log("Clearing test");
125+
m_logger->log("Print contents before clearing");
126+
cache.print(m_logger);
127+
assert(cache.getState() == "{2, 2}, {3, 3}, {1, 1}, {4, N}, {6, Y}");
128+
cache.clear();
129+
m_logger->log("Print contents after clearing");
130+
cache.print(m_logger);
131+
assert(cache.getState() == "");
132+
133+
ResizableLRUCache<int, std::string> cache2(5u);
115134

116135
cache2.insert(500, "five hundred"); //inserts at addr = 0
117136
cache2.insert(510, "five hundred and ten"); //inserts at addr = 472
@@ -124,6 +143,82 @@ class LRUCacheTestApp final : public nbl::application_templates::MonoSystemMonoL
124143
cache2.print(m_logger);
125144
cache2.insert(++i, "key is 112");
126145

146+
// Grow test - try growing the cache
147+
m_logger->log("Growing test");
148+
auto previousState = cache2.getState();
149+
// Grow cache
150+
assert(cache2.grow(10));
151+
// Cache state should be the same
152+
assert(cache2.getState() == previousState);
153+
cache2.print(m_logger);
154+
cache2.insert(++i, "key is 113");
155+
cache2.insert(++i, "key is 114");
156+
cache2.insert(++i, "key is 115");
157+
cache2.insert(++i, "key is 116");
158+
cache2.insert(++i, "key is 117");
159+
cache2.print(m_logger);
160+
// Should evict key 52
161+
cache2.insert(++i, "key is 118");
162+
cache2.print(m_logger);
163+
const auto latestState = cache2.getState();
164+
assert(latestState == "{21, key is 21}, {22, key is 22}, {23, key is 23}, {112, key is 112}, {113, key is 113}, {114, key is 114}, {115, key is 115}, {116, key is 116}, {117, key is 117}, {118, key is 118}");
165+
// Invalid grow should fail
166+
assert(!cache2.grow(5));
167+
assert(!cache2.grow(10));
168+
// Call a bunch of grows that shouldn't fail and some others that should
169+
for (auto i = 1u; i < 50; i++)
170+
{
171+
assert(cache2.grow(50 * i));
172+
assert(!cache2.grow(25 * i));
173+
assert(!cache2.grow(50 * i));
174+
assert(cache2.getState() == latestState);
175+
}
176+
177+
// Single element cache test - checking for edge cases
178+
ResizableLRUCache<int, std::string> cache3(1u);
179+
cache3.insert(0, "foo");
180+
cache3.insert(1, "bar");
181+
cache3.clear();
182+
183+
// Besides the disposal function that gets called when evicting, we need to check that the Cache properly destroys all resident `Key,Value` pairs when destroyed
184+
struct Foo
185+
{
186+
int* destroyCounter;
187+
188+
Foo(int* _destroyCounter) : destroyCounter(_destroyCounter){}
189+
190+
void operator=(Foo&& other)
191+
{
192+
destroyCounter = other.destroyCounter;
193+
other.destroyCounter = nullptr;
194+
}
195+
196+
Foo(Foo&& other)
197+
{
198+
operator=(std::move(other));
199+
}
200+
201+
~Foo()
202+
{
203+
// Only count destructions of objects resident in Cache and not ones that happen right after moving out of
204+
if (destroyCounter)
205+
(*destroyCounter)++;
206+
}
207+
};
208+
209+
int destroyCounter = 0;
210+
{
211+
ResizableLRUCache<int, Foo> cache4(10u);
212+
for (int i = 0; i < 10; i++)
213+
cache4.insert(i, Foo(&destroyCounter));
214+
int x = 0;
215+
}
216+
217+
assert(destroyCounter == 10);
218+
219+
220+
m_logger->log("all good");
221+
127222
m_textureLRUCache = std::unique_ptr<TextureLRUCache>(new TextureLRUCache(1024u));
128223
{
129224
SIntendedSubmitInfo intendedNextSubmit = {};
@@ -142,11 +237,6 @@ class LRUCacheTestApp final : public nbl::application_templates::MonoSystemMonoL
142237
TextureReference* inserted = m_textureLRUCache->insert(69420, nextSemaSignal.value, evictionCallback);
143238
}
144239

145-
#ifdef _NBL_DEBUG
146-
cache2.print(m_logger);
147-
#endif
148-
m_logger->log("all good");
149-
150240
constexpr uint32_t InvalidIdx = ~0u;
151241
struct TextureReference
152242
{
@@ -168,7 +258,7 @@ class LRUCacheTestApp final : public nbl::application_templates::MonoSystemMonoL
168258
// In LRU Cache `insert` function, in case of cache hit, we need to assign semaphore value to TextureReference without changing `alloc_idx`
169259
inline TextureReference& operator=(uint64_t semamphoreVal) { lastUsedSemaphoreValue = semamphoreVal; return *this; }
170260
};
171-
using TextureLRUCache = LRUCache<uint32_t, TextureReference>;
261+
using TextureLRUCache = ResizableLRUCache<uint32_t, TextureReference>;
172262

173263
TextureLRUCache textureCache = TextureLRUCache(3u);
174264

0 commit comments

Comments
 (0)