Add a template specialization for ConcurrentCache storing shared_ptr

When ConcurrentCache store a shared_ptr we may have shared_ptr in used
while the ConcurrentCache has drop it.
When we "recreate" a value to put in the cache, we don't want to recreate
it, but copying the shared_ptr in use.

To do so we use a (unlimited) store of weak_ptr (aka `WeakStore`)
Every created shared_ptr added to the cache has a weak_ptr ref also stored
in the WeakStore, and we check the WeakStore before creating the value.
This commit is contained in:
Matthieu Gautier
2022-05-24 16:22:06 +02:00
parent 2b38d2cf1b
commit e5ea210d2c
2 changed files with 128 additions and 0 deletions

View File

@ -107,3 +107,24 @@ TEST(ConcurrentCacheTest, handleException) {
EXPECT_EQ(val, 888);
}
TEST(ConcurrentCacheTest, weakPtr) {
kiwix::ConcurrentCache<int, std::shared_ptr<int>> cache(1);
auto refValue = cache.getOrPut(7, []() { return std::make_shared<int>(777); });
EXPECT_EQ(*refValue, 777);
EXPECT_EQ(refValue.use_count(), 2);
// This will drop shared(777) from the cache
cache.getOrPut(8, []() { return std::make_shared<int>(888); });
EXPECT_EQ(refValue.use_count(), 1);
// We must get the shared value from the weakPtr we have
EXPECT_NO_THROW(cache.getOrPut(7, []() { throw std::runtime_error("oups"); return nullptr; }));
EXPECT_EQ(refValue.use_count(), 2);
// Drop all ref
cache.getOrPut(8, []() { return std::make_shared<int>(888); });
refValue.reset();
// Be sure we call the construction function
EXPECT_THROW(cache.getOrPut(7, []() { throw std::runtime_error("oups"); return nullptr; }), std::runtime_error);
}