3030#include < limits>
3131#include < memory>
3232#include < mutex>
33+ #include < optional>
3334#include < set>
3435#include < shared_mutex>
3536#include < string>
@@ -65,7 +66,7 @@ class CCompressedLfuCache {
6566 using TDictionary = CCompressedDictionary<COMPRESSED_KEY_BITS / 64 >;
6667 using TCompressedKey = typename TDictionary::CWord;
6768 using TCompressKey = std::function<TCompressedKey(const TDictionary&, const KEY&)>;
68- using TComputeValueCallback = std::function<VALUE(KEY)>;
69+ using TComputeValueCallback = std::function<std::optional< VALUE> (KEY)>;
6970 using TReadValueCallback = std::function<void (const VALUE&, bool )>;
7071
7172public:
@@ -96,6 +97,9 @@ class CCompressedLfuCache {
9697
9798 // ! Lookup an item with \p key in the cache or else fall back to computing.
9899 // !
100+ // ! \warning If \p computeValue fails to produce a value (returns std::nullopt)
101+ // ! then \p readValue will not be called.
102+ // !
99103 // ! \param[in] key The item key.
100104 // ! \param[in] computeValue Computes the value in the case of a cache miss.
101105 // ! \param[in] readValue Processes the value.
@@ -137,15 +141,18 @@ class CCompressedLfuCache {
137141 }
138142
139143 auto value = computeValue (std::move (key));
144+ if (!value) {
145+ return false ;
146+ }
140147
141- std::size_t itemMemoryUsage{memory::dynamicSize (value)};
148+ std::size_t itemMemoryUsage{memory::dynamicSize (* value)};
142149
143150 if (this ->guardWrite (TIME_OUT, [&] {
144151 // It is possible that two values with the same key check the cache
145152 // before either takes the write lock. So check if this is already
146153 // in the cache before going any further.
147154 if (m_ItemCache.find (compressedKey) != m_ItemCache.end ()) {
148- readValue (value, true );
155+ readValue (* value, true );
149156 this ->incrementCount (compressedKey);
150157 return ;
151158 }
@@ -158,14 +165,14 @@ class CCompressedLfuCache {
158165 // It's possible that the cache is empty yet isn't big
159166 // enough to hold this new item.
160167 if (itemToEvict == m_ItemStats.end ()) {
161- readValue (value, false );
168+ readValue (* value, false );
162169 return ;
163170 }
164171 m_RemovedCount += lastEvictedCount;
165172 lastEvictedCount = itemToEvict->count ();
166173 this ->removeFromCache (itemToEvict);
167174 }
168- readValue (this ->insert (compressedKey, value, itemMemoryUsage,
175+ readValue (this ->insert (compressedKey, * value, itemMemoryUsage,
169176 count + lastEvictedCount),
170177 false );
171178 }) == false ) {
0 commit comments