Stroika Library 3.0d23
 
Loading...
Searching...
No Matches
LRUCache.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#include "Stroika/Foundation/Containers/Common.h"
6#include "Stroika/Foundation/Cryptography/Digest/Hash.h"
8
10
11 /*
12 ********************************************************************************
13 ************ LRUCache<KEY, VALUE, TRAITS>::LRUCache_::CacheIterator_ ***********
14 ********************************************************************************
15 */
16 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
17 struct LRUCache<KEY, VALUE, TRAITS>::CacheIterator_ {
18 explicit CacheIterator_ (CacheElement_** start, CacheElement_** end)
19 : fCurV{start}
20 , fEndV{end}
21 , fCur{start == end ? nullptr : *fCurV}
22 {
23 }
24 CacheIterator_& operator++ ()
25 {
26 RequireNotNull (fCur);
27 Require (fCurV != fEndV);
28 fCur = fCur->fNext;
29 if (fCur == nullptr) {
30 ++fCurV;
31 if (fCurV != fEndV) {
32 fCur = *fCurV;
33 }
34 }
35 return *this;
36 }
37 optional<KeyValuePair_>& operator* ()
38 {
39 RequireNotNull (fCur);
40 return fCur->fElement;
41 }
42 optional<KeyValuePair_>* operator->()
43 {
44 RequireNotNull (fCur);
45 return &fCur->fElement;
46 }
47 bool operator== (const CacheIterator_& rhs) const
48 {
49 return fCur == rhs.fCur;
50 }
51
52 private:
53 CacheElement_** fCurV;
54 CacheElement_** fEndV;
55 CacheElement_* fCur;
56 };
57
58 /*
59 ********************************************************************************
60 ************* LRUCache<KEY, VALUE, TRAITS>::CacheIterator_ *********************
61 ********************************************************************************
62 */
63 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
64 struct LRUCache<KEY, VALUE, TRAITS>::CacheElement_ {
65 CacheElement_* fNext{nullptr};
66 CacheElement_* fPrev{nullptr};
67 optional<KeyValuePair_> fElement{};
68 };
69
70 /*
71 ********************************************************************************
72 ********************** LRUCache<KEY, VALUE, TRAITS>> ***************************
73 ********************************************************************************
74 */
75 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
77 requires (same_as<typename TRAITS::KeyHashFunctionType, nullptr_t> and same_as<typename TRAITS::KeyEqualsCompareFunctionType, equal_to<KEY>>)
78 : LRUCache{1, equal_to<KEY>{}}
79 {
80 }
81 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
82 inline LRUCache<KEY, VALUE, TRAITS>::LRUCache (size_t maxCacheSize, const typename TRAITS::KeyEqualsCompareFunctionType& keyEqualsComparer)
83 requires (same_as<typename TRAITS::KeyHashFunctionType, nullptr_t>)
84 : fHashtableSize_{1}
85 , fKeyEqualsComparer_{keyEqualsComparer}
86 , fHashFunction_{nullptr}
87 , fCachedElts_BUF_{1}
88 , fCachedElts_First_{Memory::eUninitialized, 1}
89 , fCachedElts_Last_{Memory::eUninitialized, 1}
90 {
91 Require (maxCacheSize >= 1);
92 SetMaxCacheSize (maxCacheSize);
93 }
94 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
95 inline LRUCache<KEY, VALUE, TRAITS>::LRUCache (size_t maxCacheSize, const typename TRAITS::KeyEqualsCompareFunctionType& keyEqualsComparer,
96 size_t hashTableSize, const typename TRAITS::KeyHashFunctionType& hashFunction)
97 requires (not same_as<typename TRAITS::KeyHashFunctionType, nullptr_t>)
98 : fHashtableSize_{hashTableSize}
99 , fKeyEqualsComparer_{keyEqualsComparer}
100 , fHashFunction_{hashFunction}
101 , fCachedElts_BUF_{hashTableSize}
102 , fCachedElts_First_{Memory::eUninitialized, hashTableSize}
103 , fCachedElts_Last_{Memory::eUninitialized, hashTableSize}
104 {
105 Require (hashTableSize >= 1);
106 WeakAssert (maxCacheSize >= hashTableSize); // plausibly a bug if violated, but no biggie since SetMaxCacheSize() adjusts
107 SetMaxCacheSize (maxCacheSize);
108 }
109 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
110 inline LRUCache<KEY, VALUE, TRAITS>::LRUCache (size_t maxCacheSize, size_t hashTableSize, const typename TRAITS::KeyHashFunctionType& hashFunction)
111 requires (not same_as<typename TRAITS::KeyHashFunctionType, nullptr_t>)
112 : LRUCache{maxCacheSize, typename TRAITS::KeyEqualsCompareFunctionType{}, hashTableSize, hashFunction}
113 {
114 }
115 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
116 inline LRUCache<KEY, VALUE, TRAITS>::LRUCache (LRUCache&& from)
117 // This is really the same as a copy, because moving is hard. This data structure contains lots of internal pointers.
118 // @todo it would make sense to do a move here. Much of the memory could be just shuffled over in many cases - but
119 // all the internal pointers would need to be patched. NOTE - important to not wrap from in move() for forward, cuz we want the lvalue version
120 : LRUCache{from}
121 {
122 }
123 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
124 LRUCache<KEY, VALUE, TRAITS>::LRUCache (const LRUCache& from)
125 requires (same_as<typename TRAITS::KeyHashFunctionType, nullptr_t>)
126 : LRUCache{from.GetMaxCacheSize (), from.GetKeyEqualsCompareFunction ()}
127 {
128 shared_lock lockSrc{from.fMaybeMutex_}; // no need to lock THIS guy cuz CTOR, nobody could have reference to it yet
129 for (CacheIterator_ i = from.begin_ (); i != from.end_ (); ++i) {
130 if (*i) {
131 Add_ ((*i)->fKey, (*i)->fValue);
132 }
133 }
134 }
135 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
136 LRUCache<KEY, VALUE, TRAITS>::LRUCache (const LRUCache& from)
137 requires (not same_as<typename TRAITS::KeyHashFunctionType, nullptr_t>)
138 : LRUCache{from.GetMaxCacheSize (), from.GetKeyEqualsCompareFunction (), from.GetHashTableSize (), from.GetKeyHashFunction ()}
139 {
140 shared_lock lockSrc{from.fMaybeMutex_}; // no need to lock THIS guy cuz CTOR, nobody could have reference to it yet
141 for (CacheIterator_ i = from.begin_ (); i != from.end_ (); ++i) {
142 if (*i) {
143 Add_ ((*i)->fKey, (*i)->fValue);
144 }
145 }
146 }
147 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
148 inline auto LRUCache<KEY, VALUE, TRAITS>::operator= (LRUCache&& rhs) noexcept -> LRUCache&
149 {
150 IgnoreExceptionsForCall (return operator= (rhs)); // same as assign, cuz hard to move - see move constructor
151 }
152 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
153 auto LRUCache<KEY, VALUE, TRAITS>::operator= (const LRUCache& rhs) -> LRUCache&
154 {
155 if (this != &rhs) {
156 //shared_lock lockSrc{rhs.fMaybeMutex_}; -- lock should not be needed cuz rhs.Elements() locks and makes a copy
157 SetMaxCacheSize (rhs.GetMaxCacheSize ());
158 scoped_lock critSec{fMaybeMutex_};
159 ClearCache_ ();
160 for (const auto& i : rhs.Elements ()) {
161 if (i.fKey) {
162 Add_ (*i.fKey, *i.fValue);
163 }
164 }
165 }
166 return *this;
167 }
168 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
169 inline size_t LRUCache<KEY, VALUE, TRAITS>::GetMaxCacheSize () const
170 {
171 shared_lock critSec{fMaybeMutex_};
172 return fHashtableSize_ * fCachedElts_BUF_[0].size ();
173 }
174 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
176 {
177 Require (maxCacheSize >= 1);
178 scoped_lock critSec{fMaybeMutex_};
179 maxCacheSize = ((maxCacheSize + fHashtableSize_ - 1) / fHashtableSize_); // divide size over number of hash chains
180 maxCacheSize = max (maxCacheSize, static_cast<size_t> (1)); // must be at least one per chain
181 for (size_t hi = 0; hi < fHashtableSize_; ++hi) {
182 if (maxCacheSize != fCachedElts_BUF_[hi].size ()) {
183 fCachedElts_BUF_[hi].resize (maxCacheSize);
184 // Initially link LRU together.
185 fCachedElts_First_[hi] = Containers::Start (fCachedElts_BUF_[hi]);
186 fCachedElts_Last_[hi] = fCachedElts_First_[hi] + maxCacheSize - 1;
187 fCachedElts_BUF_[hi][0].fPrev = nullptr;
188 for (size_t i = 0; i < maxCacheSize - 1; ++i) {
189 fCachedElts_BUF_[hi][i].fNext = fCachedElts_First_[hi] + (i + 1);
190 fCachedElts_BUF_[hi][i + 1].fPrev = fCachedElts_First_[hi] + (i);
191 }
192 fCachedElts_BUF_[hi][maxCacheSize - 1].fNext = nullptr;
193 }
194 }
195 }
196 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
197 inline auto LRUCache<KEY, VALUE, TRAITS>::GetKeyEqualsCompareFunction () const -> KeyEqualsCompareFunctionType
198 {
199 shared_lock critSec{fMaybeMutex_};
200 return fKeyEqualsComparer_;
201 }
202 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
203 inline auto LRUCache<KEY, VALUE, TRAITS>::GetStats () const -> StatsType
204 {
205 shared_lock critSec{fMaybeMutex_};
206 return fStats_;
207 }
208 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
209 inline auto LRUCache<KEY, VALUE, TRAITS>::GetHashTableSize () const -> size_t
210 {
211 shared_lock critSec{fMaybeMutex_};
212 if constexpr (same_as<typename TRAITS::KeyHashFunctionType, nullptr_t>) {
213 return 1;
214 }
215 else {
216 return fHashtableSize_;
217 }
218 }
219 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
220 inline auto LRUCache<KEY, VALUE, TRAITS>::GetKeyHashFunction () const -> typename TRAITS::KeyHashFunctionType
221 {
222 shared_lock critSec{fMaybeMutex_};
223 return fHashFunction_;
224 }
225 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
227 {
228 scoped_lock critSec{fMaybeMutex_};
229 ClearCache_ ();
230 }
231 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
233 {
234 scoped_lock critSec{fMaybeMutex_};
235 optional<KeyValuePair_>* v = LookupElement_ (key);
236 if (v != nullptr) {
237 v->clear ();
238 }
239 Ensure (not Lookup (key));
240 }
241 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
242 void LRUCache<KEY, VALUE, TRAITS>::clear (function<bool (typename Common::ArgByValueType<KEY>)> clearPredicate)
243 {
244 scoped_lock critSec{fMaybeMutex_};
245 for (auto i = begin_ (); i != end_ (); ++i) {
246 if (i->has_value () and clearPredicate ((*i)->fKey)) {
247 *i = nullopt;
248 }
249 }
250 }
251 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
252 template <qCompilerAndStdLib_ConstraintDiffersInTemplateRedeclaration_BWA (predicate<KEY>) PREDICATE>
253 void LRUCache<KEY, VALUE, TRAITS>::RemoveAll (PREDICATE&& removeIfReturnsTrue)
254 {
255 scoped_lock critSec{fMaybeMutex_};
256 for (auto i = begin_ (); i != end_ (); ++i) {
257 if (i->has_value () and forward<PREDICATE> (removeIfReturnsTrue) ((*i)->fKey)) {
258 *i = nullopt;
259 }
260 }
261 }
262 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
263 template <typename V>
264 requires (not IValuelessCache<V>)
265 auto LRUCache<KEY, VALUE, TRAITS>::Lookup (typename Common::ArgByValueType<KEY> key) -> optional<V>
266 {
267 scoped_lock critSec{fMaybeMutex_}; // subtle - WRITE cuz updates LRU
268 optional<KeyValuePair_>* v = LookupElement_ (key);
269 if (v == nullptr) {
270 return optional<VALUE>{};
271 }
272 Ensure (fKeyEqualsComparer_ (key, (*v)->fKey));
273 return (*v)->fValue;
274 }
275 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
276 template <typename V>
277 requires (IValuelessCache<V>)
279 {
280 scoped_lock critSec{fMaybeMutex_}; // subtle - WRITE cuz updates LRU
281 optional<KeyValuePair_>* v = LookupElement_ (key);
282 if (v == nullptr) {
283 return optional<KEY>{};
284 }
285 Ensure (fKeyEqualsComparer_ (key, (*v)->fKey));
286 return (*v)->fKey;
287 }
288 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
289 template <typename V>
290 requires (not IValuelessCache<V>)
292 {
293 scoped_lock critSec{fMaybeMutex_};
294 Add_ (key, value);
295 }
296 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
297 template <typename V>
298 requires (IValuelessCache<V>)
300 {
301 scoped_lock critSec{fMaybeMutex_};
302 optional<KeyValuePair_>* v = AddNewButDontFillIn_ (key);
303 v->emplace (KeyValuePair_{.fKey = key});
304 }
305 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
306 void LRUCache<KEY, VALUE, TRAITS>::Add_ (typename Common::ArgByValueType<KEY> key, typename Common::ArgByValueType<VALUE> value)
307 {
308 optional<KeyValuePair_>* v = AddNewButDontFillIn_ (key);
309 v->emplace (KeyValuePair_{.fKey = key, .fValue = value});
310 }
311 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
312 inline size_t LRUCache<KEY, VALUE, TRAITS>::H_ ([[maybe_unused]] typename Common::ArgByValueType<KEY> k) const
313 {
314 Assert (fHashtableSize_ >= 1);
315 if constexpr (same_as<typename TRAITS::KeyHashFunctionType, nullptr_t>) {
316 return 0; // avoid referencing hash function
317 }
318 else {
319 return fHashFunction_ (k) % fHashtableSize_;
320 }
321 }
322 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
323 auto LRUCache<KEY, VALUE, TRAITS>::Elements () const -> Containers::Mapping<KEY, VALUE>
324 {
326 shared_lock critSec{fMaybeMutex_};
327 for (CacheIterator_ i = begin_ (); i != end_ (); ++i) {
328 if (*i) {
329 result.Add ((*i)->fKey, (*i)->fValue);
330 }
331 }
332 return result;
333 }
334 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
336 const function<VALUE (typename Common::ArgByValueType<KEY>)>& valueFetcher)
337 {
338 auto v = Lookup (key);
339 if (v.has_value ()) {
340 return *v;
341 }
342 else {
343 VALUE newV = valueFetcher (key);
344 Add (key, newV);
345 return newV;
346 }
347 }
348 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
349 inline auto LRUCache<KEY, VALUE, TRAITS>::begin_ () const -> CacheIterator_
350 {
351 LRUCache* ncThis = const_cast<LRUCache*> (this); // http://stroika-bugs.sophists.com/browse/STK-764
352 return CacheIterator_{std::begin (ncThis->fCachedElts_First_), std::end (ncThis->fCachedElts_First_)};
353 }
354 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
355 inline typename LRUCache<KEY, VALUE, TRAITS>::CacheIterator_ LRUCache<KEY, VALUE, TRAITS>::end_ () const
356 {
357 return CacheIterator_{nullptr, nullptr};
358 }
359 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
360 inline void LRUCache<KEY, VALUE, TRAITS>::ShuffleToHead_ (size_t chainIdx, CacheElement_* b)
361 {
362 Require (chainIdx < fHashtableSize_);
363 RequireNotNull (b);
364 if (b == fCachedElts_First_[chainIdx]) {
365 Assert (b->fPrev == nullptr);
366 return; // already at head
367 }
368 CacheElement_* prev = b->fPrev;
369 AssertNotNull (prev); // don't call this if already at head
370 // patch following and preceeding blocks to point to each other
371 prev->fNext = b->fNext;
372 if (b->fNext == nullptr) {
373 Assert (b == fCachedElts_Last_[chainIdx]);
374 fCachedElts_Last_[chainIdx] = b->fPrev;
375 }
376 else {
377 b->fNext->fPrev = prev;
378 }
379
380 // Now patch us into the head of the list
381 CacheElement_* oldFirst = fCachedElts_First_[chainIdx];
382 AssertNotNull (oldFirst);
383 b->fNext = oldFirst;
384 oldFirst->fPrev = b;
385 b->fPrev = nullptr;
386 fCachedElts_First_[chainIdx] = b;
387
388 Ensure (fCachedElts_Last_[chainIdx] != nullptr and fCachedElts_Last_[chainIdx]->fNext == nullptr);
389 Ensure (fCachedElts_First_[chainIdx] != nullptr and fCachedElts_First_[chainIdx] == b and
390 fCachedElts_First_[chainIdx]->fPrev == nullptr and fCachedElts_First_[chainIdx]->fNext != nullptr);
391 }
392 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
393 inline void LRUCache<KEY, VALUE, TRAITS>::ClearCache_ ()
394 {
395 for (size_t hi = 0; hi < fHashtableSize_; ++hi) {
396 for (CacheElement_* cur = fCachedElts_First_[hi]; cur != nullptr; cur = cur->fNext) {
397 cur->fElement = nullopt;
398 }
399 }
400 }
401 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
402 inline auto LRUCache<KEY, VALUE, TRAITS>::LookupElement_ (typename Common::ArgByValueType<KeyType> item) -> optional<KeyValuePair_>*
403 {
404 size_t chainIdx = H_ (item);
405 Assert (0 <= chainIdx and chainIdx < fHashtableSize_);
406 for (CacheElement_* cur = fCachedElts_First_[chainIdx]; cur != nullptr; cur = cur->fNext) {
407 if (cur->fElement and fKeyEqualsComparer_ (cur->fElement->fKey, item)) {
408 ShuffleToHead_ (chainIdx, cur);
409 fStats_.IncrementHits ();
410 return &fCachedElts_First_[chainIdx]->fElement;
411 }
412 }
413 fStats_.IncrementMisses ();
414 return nullptr;
415 }
416 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS>
417 inline auto LRUCache<KEY, VALUE, TRAITS>::AddNewButDontFillIn_ (typename Common::ArgByValueType<KeyType> item) -> optional<KeyValuePair_>*
418 {
419 size_t chainIdx = H_ (item);
420 Assert (0 <= chainIdx and chainIdx < fHashtableSize_);
421 ShuffleToHead_ (chainIdx, fCachedElts_Last_[chainIdx]);
422 return &fCachedElts_First_[chainIdx]->fElement;
423 }
424
425 /*
426 ********************************************************************************
427 **** Factory::LRUCache::Maker<KEY,VALUE,InternallySynchronized,STATS_TYPE> *****
428 ********************************************************************************
429 */
430 namespace Factory::LRUCache {
431 template <typename KEY, typename VALUE, InternallySynchronized internallySynchronized, typename STATS_TYPE>
432 template <Common::IEqualsComparer<KEY> KEY_EQUALS_COMPARER>
433#if __cplusplus >= kStrokia_Foundation_Common_cplusplus_23 || _HAS_CXX23 /*vis studio uses _HAS_CXX23 */
434 inline auto Maker<KEY, VALUE, internallySynchronized, STATS_TYPE>::operator() (size_t maxCacheSize, KEY_EQUALS_COMPARER&& keyComparer)
435#else
436 inline auto Maker<KEY, VALUE, internallySynchronized, STATS_TYPE>::operator() (size_t maxCacheSize, KEY_EQUALS_COMPARER&& keyComparer) const
437#endif
438 {
439 using namespace LRUCacheSupport;
440 using TRAITS_ = WithKeyComparerTraits<DefaultTraits<KEY, VALUE>, KEY_EQUALS_COMPARER>;
441 if constexpr (internallySynchronized == Execution::InternallySynchronized::eInternallySynchronized) {
442 return Cache::LRUCache<KEY, VALUE, InternallySynchronizedTraits<TRAITS_>>{maxCacheSize, forward<KEY_EQUALS_COMPARER> (keyComparer)};
443 }
444 else {
445 return Cache::LRUCache<KEY, VALUE, TRAITS_>{maxCacheSize, forward<KEY_EQUALS_COMPARER> (keyComparer)};
446 }
447 }
448 template <typename KEY, typename VALUE, InternallySynchronized internallySynchronized, typename STATS_TYPE>
449 template <typename KEY_HASH_FUNCTION>
450#if __cplusplus >= kStrokia_Foundation_Common_cplusplus_23 || _HAS_CXX23 /*vis studio uses _HAS_CXX23 */
451 inline auto Maker<KEY, VALUE, internallySynchronized, STATS_TYPE>::operator() (size_t maxCacheSize, size_t hashTableSize,
452 KEY_HASH_FUNCTION&& hashFunction)
453#else
454 inline auto Maker<KEY, VALUE, internallySynchronized, STATS_TYPE>::operator() (size_t maxCacheSize, size_t hashTableSize,
455 KEY_HASH_FUNCTION&& hashFunction) const
456#endif
457 {
458 Require (maxCacheSize >= hashTableSize);
459 using namespace LRUCacheSupport;
460 using TRAITS_ = WithKeyHashTraits<DefaultTraits<KEY, VALUE>, KEY_HASH_FUNCTION>;
461 if constexpr (internallySynchronized == InternallySynchronized::eInternallySynchronized) {
462 return Cache::LRUCache<KEY, VALUE, InternallySynchronizedTraits<TRAITS_>>{maxCacheSize, equal_to<KEY>{}, hashTableSize, hashFunction};
463 }
464 else {
465 return Cache::LRUCache<KEY, VALUE, TRAITS_>{maxCacheSize, equal_to<KEY>{}, hashTableSize, hashFunction};
466 }
467 }
468 template <typename KEY, typename VALUE, InternallySynchronized internallySynchronized, typename STATS_TYPE>
469 template <typename KEY_EQUALS_COMPARER, typename KEY_HASH_FUNCTION>
470#if __cplusplus >= kStrokia_Foundation_Common_cplusplus_23 || _HAS_CXX23 /*vis studio uses _HAS_CXX23 */
471 inline auto Maker<KEY, VALUE, internallySynchronized, STATS_TYPE>::operator() (size_t maxCacheSize, KEY_EQUALS_COMPARER&& keyComparer,
472 size_t hashTableSize, KEY_HASH_FUNCTION&& hashFunction)
473#else
474 inline auto Maker<KEY, VALUE, internallySynchronized, STATS_TYPE>::operator() (size_t maxCacheSize, KEY_EQUALS_COMPARER&& keyComparer,
475 size_t hashTableSize, KEY_HASH_FUNCTION&& hashFunction) const
476#endif
477 {
478 Require (maxCacheSize >= hashTableSize);
479 using namespace LRUCacheSupport;
480 using TRAITS_ = WithKeyHashTraits<WithKeyComparerTraits<DefaultTraits<KEY, VALUE>, KEY_EQUALS_COMPARER>, KEY_HASH_FUNCTION>;
481 if constexpr (internallySynchronized == InternallySynchronized::eInternallySynchronized) {
482 return Cache::LRUCache<KEY, VALUE, InternallySynchronizedTraits<TRAITS_>>{maxCacheSize, keyComparer, hashTableSize, hashFunction};
483 }
484 else {
485 return Cache::LRUCache<KEY, VALUE, TRAITS_>{maxCacheSize, keyComparer, hashTableSize, hashFunction};
486 }
487 }
488 }
489
490 ///
491 /// DEPRECATED CLASS TEMPLATES
492 ///
493 template <typename KEY, typename VALUE, LRUCacheSupport::ITraits<KEY, VALUE> TRAITS = LRUCacheSupport::DefaultTraits<KEY, VALUE>>
495 [[deprecated ("Since Stroika v3.0d23 - use LRUCacheSupport::InternallySynchronizedTraits or Factory::LRUCache::Maker<string, "
496 "string,InternallySynchronized::eInternallySynchronized>{}(3)")]] =
498
499 namespace Factory {
500 template <typename KEY, typename VALUE, typename STATS_TYPE = Statistics::StatsType_DEFAULT>
501 struct [[deprecated ("Since Stroika v3.0d23 use Factory::LRUCache::Maker<KEY,VALUE>")]] LRUCache_NoHash {
502 template <Common::IEqualsComparer<KEY> KEY_EQUALS_COMPARER = equal_to<KEY>>
503 auto operator() (size_t maxCacheSize = 1, const KEY_EQUALS_COMPARER& keyComparer = {}) const
504 {
506 maxCacheSize, keyComparer);
507 }
508 };
509 template <typename KEY, typename VALUE, typename STATS_TYPE = Statistics::StatsType_DEFAULT, typename DEFAULT_KEY_EQUALS_COMPARER = equal_to<KEY>>
510 struct [[deprecated ("Since Stroika v3.0d23 use Factory::LRUCache::Maker<KEY,VALUE>")]] LRUCache_WithHash {
511 template <typename KEY_HASH_FUNCTION = hash<KEY>>
512 auto operator() (size_t maxCacheSize, size_t hashTableSize, const KEY_HASH_FUNCTION& hashFunction = {}) const
513 {
515 maxCacheSize, DEFAULT_KEY_EQUALS_COMPARER{}, hashTableSize, hashFunction);
516 }
517 template <typename KEY_EQUALS_COMPARER, typename KEY_HASH_FUNCTION = hash<KEY>>
518 auto operator() (size_t maxCacheSize, const KEY_EQUALS_COMPARER& keyComparer, size_t hashTableSize,
519 const KEY_HASH_FUNCTION& hashFunction = {}) const
520 {
522 maxCacheSize, keyComparer, hashTableSize, hashFunction);
523 }
524 };
525 template <typename KEY, typename VALUE, typename STATS_TYPE = Statistics::StatsType_DEFAULT>
526 struct [[deprecated ("Since Stroika v3.0d23 use Factory::LRUCache::Maker<KEY, "
527 "VALUE,InternallySynchronized::eInternallySynchronized>")]] SynchronizedLRUCache_NoHash {
528 template <Common::IEqualsComparer<KEY> KEY_EQUALS_COMPARER = equal_to<KEY>>
529 auto operator() (size_t maxCacheSize = 1, const KEY_EQUALS_COMPARER& keyComparer = {}) const
530 {
532 }
533 };
534 template <typename KEY, typename VALUE, typename STATS_TYPE = Statistics::StatsType_DEFAULT, typename DEFAULT_KEY_EQUALS_COMPARER = equal_to<KEY>>
535 struct [[deprecated ("Since Stroika v3.0d23 use Factory::LRUCache::Maker<KEY, "
536 "VALUE,Execution::InternallySynchronized::eInternallySynchronized>")]] SynchronizedLRUCache_WithHash {
537 template <typename KEY_HASH_FUNCTION = hash<KEY>>
538 auto operator() (size_t maxCacheSize, size_t hashTableSize, const KEY_HASH_FUNCTION& hashFunction = {}) const
539 {
541 maxCacheSize, hashTableSize, hashFunction);
542 }
543 template <typename KEY_EQUALS_COMPARER, typename KEY_HASH_FUNCTION = hash<KEY>>
544 auto operator() (size_t maxCacheSize, const KEY_EQUALS_COMPARER& keyComparer, size_t hashTableSize,
545 const KEY_HASH_FUNCTION& hashFunction = {}) const
546 {
548 maxCacheSize, keyComparer, hashTableSize, hashFunction);
549 }
550 };
551
552 }
553
554}
#define AssertNotNull(p)
Definition Assertions.h:334
#define RequireNotNull(p)
Definition Assertions.h:348
#define WeakAssert(c)
A WeakAssert() is for things that aren't guaranteed to be true, but are overwhelmingly likely to be t...
Definition Assertions.h:439
LRUCache implements a simple least-recently-used caching strategy, with optional hashing (of keys) to...
Definition LRUCache.h:224
nonvirtual void Add(typename Common::ArgByValueType< KEY > key, typename Common::ArgByValueType< V > value)
nonvirtual optional< V > Lookup(typename Common::ArgByValueType< KEY > key)
nonvirtual VALUE LookupValue(typename Common::ArgByValueType< KEY > key, const function< VALUE(typename Common::ArgByValueType< KEY >)> &valueFetcher)
Definition LRUCache.inl:335
nonvirtual void RemoveAll(PREDICATE &&removeIfReturnsTrue)
nonvirtual Containers::Mapping< KEY, VALUE > Elements() const
Definition LRUCache.inl:323
nonvirtual void SetMaxCacheSize(size_t maxCacheSize)
Definition LRUCache.inl:175
nonvirtual bool Add(ArgByValueType< key_type > key, ArgByValueType< mapped_type > newElt, AddReplaceMode addReplaceMode=AddReplaceMode::eAddReplaces)
Definition Mapping.inl:188
conditional_t<(sizeof(CHECK_T)<=2 *sizeof(void *)) and is_trivially_copyable_v< CHECK_T >, CHECK_T, const CHECK_T & > ArgByValueType
This is an alias for 'T' - but how we want to pass it on stack as formal parameter.
Definition TypeHints.h:36
CONTAINER::value_type * Start(CONTAINER &c)
For a contiguous container (such as a vector or basic_string) - find the pointer to the start of the ...
Utility to make it easier to construct a LRUCache constexpr/type name from a few parameters and types...
Definition LRUCache.h:543
static auto operator()(size_t maxCacheSize=1, KEY_EQUALS_COMPARER &&keyComparer={})
NOHASH versions.
Definition LRUCache.inl:434