diff --git a/vespalib/src/tests/stllike/cache_test.cpp b/vespalib/src/tests/stllike/cache_test.cpp index a3fe1c47768..5a8298917b2 100644 --- a/vespalib/src/tests/stllike/cache_test.cpp +++ b/vespalib/src/tests/stllike/cache_test.cpp @@ -12,7 +12,9 @@ class Map : public std::map { using const_iterator = typename std::map::const_iterator; using M = std::map; public: - bool read(const K & k, V & v) const { + mutable std::string _forwarded_arg; + + bool read(const K& k, V& v) const { const_iterator found = M::find(k); bool ok(found != this->end()); if (ok) { @@ -20,6 +22,10 @@ class Map : public std::map { } return ok; } + bool read(const K& k, V& v, std::string_view arg) const { + _forwarded_arg = arg; + return read(k, v); + } void write(const K & k, const V & v) { (*this)[k] = v; } @@ -196,4 +202,17 @@ TEST("testOnInsertonRemoveCalledWhenFull") { EXPECT_FALSE(cache.hasKey(3)); } +TEST("Can forward arguments to backing store on cache miss") { + B m; + cache> cache(m, -1); + m[123] = "foo"; + EXPECT_EQUAL(cache.read(123, "hello cache world"), "foo"); + EXPECT_EQUAL(m._forwarded_arg, "hello cache world"); + + // Already cached; no forwarding. + m._forwarded_arg.clear(); + EXPECT_EQUAL(cache.read(123, "goodbye cache moon"), "foo"); + EXPECT_EQUAL(m._forwarded_arg, ""); +} + TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/vespalib/src/vespa/vespalib/stllike/cache.h b/vespalib/src/vespa/vespalib/stllike/cache.h index 27ee23acd87..ad1c82a93de 100644 --- a/vespalib/src/vespa/vespalib/stllike/cache.h +++ b/vespalib/src/vespa/vespalib/stllike/cache.h @@ -95,8 +95,12 @@ class cache : private lrucache_map

* and the cache will be updated. * If none exist an empty one will be created. * Object is then put at head of LRU list. + * + * If any more arguments than `key` are present, they will be forwarded verbatim to the + * backing store in case of a cache miss. They are entirely ignored if there is a cache hit. */ - V read(const K & key); + template + V read(const K& key, BackingStoreArgs&&... backing_store_args); /** * Update the cache and write through to backing store. diff --git a/vespalib/src/vespa/vespalib/stllike/cache.hpp b/vespalib/src/vespa/vespalib/stllike/cache.hpp index 7dc90c895a3..a1a0a2c0317 100644 --- a/vespalib/src/vespa/vespalib/stllike/cache.hpp +++ b/vespalib/src/vespa/vespalib/stllike/cache.hpp @@ -81,9 +81,10 @@ cache

::getGuard() const { return UniqueLock(_hashLock); } -template< typename P > +template +template typename P::Value -cache

::read(const K & key) +cache

::read(const K& key, BackingStoreArgs&&... backing_store_args) { { std::lock_guard guard(_hashLock); @@ -105,7 +106,7 @@ cache

::read(const K & key) } } V value; - if (_store.read(key, value)) { + if (_store.read(key, value, std::forward(backing_store_args)...)) { std::lock_guard guard(_hashLock); Lru::insert(key, value); _sizeBytes.store(sizeBytes() + calcSize(key, value), std::memory_order_relaxed);