From fd2fc63dd3c1c7d7788c4e16b979d82c90eafba2 Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 25 Dec 2023 13:50:58 +0100 Subject: [PATCH] Support heterogeneous lookup in GenericObjectCache --- .../resource/testobjectcache.cpp | 57 +++++++++++++++++++ components/resource/objectcache.hpp | 17 ++++-- 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/apps/openmw_test_suite/resource/testobjectcache.cpp b/apps/openmw_test_suite/resource/testobjectcache.cpp index 25b6d87e52..1c8cff6af0 100644 --- a/apps/openmw_test_suite/resource/testobjectcache.cpp +++ b/apps/openmw_test_suite/resource/testobjectcache.cpp @@ -288,5 +288,62 @@ namespace Resource EXPECT_EQ(cache->lowerBound(4), std::nullopt); } + + TEST(ResourceGenericObjectCacheTest, addEntryToObjectCacheShouldSupportHeterogeneousLookup) + { + osg::ref_ptr> cache(new GenericObjectCache); + const std::string key = "key"; + osg::ref_ptr value(new Object); + cache->addEntryToObjectCache(std::string_view("key"), value); + EXPECT_EQ(cache->getRefFromObjectCache(key), value); + } + + TEST(ResourceGenericObjectCacheTest, addEntryToObjectCacheShouldKeyMoving) + { + osg::ref_ptr> cache(new GenericObjectCache); + std::string key(128, 'a'); + osg::ref_ptr value(new Object); + cache->addEntryToObjectCache(std::move(key), value); + EXPECT_EQ(key, ""); + EXPECT_EQ(cache->getRefFromObjectCache(std::string(128, 'a')), value); + } + + TEST(ResourceGenericObjectCacheTest, removeFromObjectCacheShouldSupportHeterogeneousLookup) + { + osg::ref_ptr> cache(new GenericObjectCache); + const std::string key = "key"; + osg::ref_ptr value(new Object); + cache->addEntryToObjectCache(key, value); + ASSERT_EQ(cache->getRefFromObjectCache(key), value); + cache->removeFromObjectCache(std::string_view("key")); + EXPECT_EQ(cache->getRefFromObjectCacheOrNone(key), std::nullopt); + } + + TEST(ResourceGenericObjectCacheTest, getRefFromObjectCacheShouldSupportHeterogeneousLookup) + { + osg::ref_ptr> cache(new GenericObjectCache); + const std::string key = "key"; + osg::ref_ptr value(new Object); + cache->addEntryToObjectCache(key, value); + EXPECT_EQ(cache->getRefFromObjectCache(std::string_view("key")), value); + } + + TEST(ResourceGenericObjectCacheTest, getRefFromObjectCacheOrNoneShouldSupportHeterogeneousLookup) + { + osg::ref_ptr> cache(new GenericObjectCache); + const std::string key = "key"; + osg::ref_ptr value(new Object); + cache->addEntryToObjectCache(key, value); + EXPECT_THAT(cache->getRefFromObjectCacheOrNone(std::string_view("key")), Optional(value)); + } + + TEST(ResourceGenericObjectCacheTest, checkInObjectCacheShouldSupportHeterogeneousLookup) + { + osg::ref_ptr> cache(new GenericObjectCache); + const std::string key = "key"; + osg::ref_ptr value(new Object); + cache->addEntryToObjectCache(key, value); + EXPECT_TRUE(cache->checkInObjectCache(std::string_view("key"), 0)); + } } } diff --git a/components/resource/objectcache.hpp b/components/resource/objectcache.hpp index 08ef0dc060..066f5b1d3e 100644 --- a/components/resource/objectcache.hpp +++ b/components/resource/objectcache.hpp @@ -81,14 +81,19 @@ namespace Resource } /** Add a key,object,timestamp triple to the Registry::ObjectCache.*/ - void addEntryToObjectCache(const KeyType& key, osg::Object* object, double timestamp = 0.0) + template + void addEntryToObjectCache(K&& key, osg::Object* object, double timestamp = 0.0) { std::lock_guard lock(_objectCacheMutex); - _objectCache[key] = Item{ object, timestamp }; + const auto it = _objectCache.find(key); + if (it == _objectCache.end()) + _objectCache.emplace_hint(it, std::forward(key), Item{ object, timestamp }); + else + it->second = Item{ object, timestamp }; } /** Remove Object from cache.*/ - void removeFromObjectCache(const KeyType& key) + void removeFromObjectCache(const auto& key) { std::lock_guard lock(_objectCacheMutex); typename ObjectCacheMap::iterator itr = _objectCache.find(key); @@ -97,7 +102,7 @@ namespace Resource } /** Get an ref_ptr from the object cache*/ - osg::ref_ptr getRefFromObjectCache(const KeyType& key) + osg::ref_ptr getRefFromObjectCache(const auto& key) { std::lock_guard lock(_objectCacheMutex); typename ObjectCacheMap::iterator itr = _objectCache.find(key); @@ -107,7 +112,7 @@ namespace Resource return nullptr; } - std::optional> getRefFromObjectCacheOrNone(const KeyType& key) + std::optional> getRefFromObjectCacheOrNone(const auto& key) { const std::lock_guard lock(_objectCacheMutex); const auto it = _objectCache.find(key); @@ -117,7 +122,7 @@ namespace Resource } /** Check if an object is in the cache, and if it is, update its usage time stamp. */ - bool checkInObjectCache(const KeyType& key, double timeStamp) + bool checkInObjectCache(const auto& key, double timeStamp) { std::lock_guard lock(_objectCacheMutex); typename ObjectCacheMap::iterator itr = _objectCache.find(key);