4#include "Stroika/Foundation/Containers/Mapping.h"
7#include "Stroika/Foundation/Execution/Common.h"
16 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
18 inline auto TimedCache<KEY, VALUE, TRAITS>::MyResult_::MakeCacheElement (
const K& key)
const -> CacheElement
20 if constexpr (kTrackExpiration) {
21 if constexpr (same_as<void, VALUE>) {
22 return CacheElement{.fKey = key, .fExpiresAt = fExpiresAt};
25 return CacheElement{.fKey = key, .fValue = fResult, .fExpiresAt = fExpiresAt};
28 else if constexpr (kTrackFreshness) {
29 if constexpr (same_as<void, VALUE>) {
30 return CacheElement{.fKey = key, .fLastRefreshedAt = fLastRefreshedAt};
33 return CacheElement{.fKey = key, .fValue = fResult, .fLastRefreshedAt = fLastRefreshedAt};
43 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
45 requires (not is_empty_v<
decltype (TRAITS::kDefaultMaxAge)>)
47 if constexpr (TRAITS::kPerCacheMaxAge) {
48 fMaxAge_ = TRAITS::kDefaultMaxAge;
51 fNextAutoClearAt_ = TRAITS::GetCurrentTimestamp () + TRAITS::kAutomaticPurgeFrequency;
54 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
56 requires (TRAITS::kPerCacheMaxAge)
58 , fNextAutoClearAt_{TRAITS::GetCurrentTimestamp () + TRAITS::kAutomaticPurgeFrequency}
60 Require (fMaxAge_ > 0.0s);
62 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
64 : fMaxAge_{src.fMaxAge_}
65 , fNextAutoClearAt_{src.fNextAutoClearAt_}
67 [[maybe_unused]]
auto&& srcLock = scoped_lock{src.fMaybeMutex_};
68 fData_ = move (src.fData_);
69 fStats_ = move (src.fStats_);
71 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
73 : fMaxAge_{src.fMaxAge_}
74 , fNextAutoClearAt_{src.fNextAutoClearAt_}
76 [[maybe_unused]]
auto&& srcLock = shared_lock{src.fMaybeMutex_};
78 fStats_ = src.fStats_;
80 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
81 inline auto TimedCache<KEY, VALUE, TRAITS>::operator= (TimedCache&& rhs)
noexcept -> TimedCache&
83 [[maybe_unused]]
auto&& locks = scoped_lock{rhs.fMaybeMutex_, fMaybeMutex_};
84 fMaxAge_ = rhs.fMaxAge_;
85 fNextAutoClearAt_ = rhs.fNextAutoClearAt_;
86 fData_ = move (rhs.fData_);
87 fStats_ = move (rhs.fStats_);
90 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
91 inline auto TimedCache<KEY, VALUE, TRAITS>::operator= (
const TimedCache& rhs) -> TimedCache&
93 [[maybe_unused]]
auto&& locks = scoped_lock{rhs.fMaybeMutex_, fMaybeMutex_};
94 fMaxAge_ = rhs.fMaxAge_;
95 fNextAutoClearAt_ = rhs.fNextAutoClearAt_;
97 fStats_ = rhs.fStats_;
100 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
101 inline bool TimedCache<KEY, VALUE, TRAITS>::Expired_ (
const MyResult_& r, TimeStampType now)
const
104 if constexpr (kTrackExpiration) {
105 expiresAt = r.fExpiresAt;
107 else if constexpr (kTrackFreshness) {
108 expiresAt = r.fLastRefreshedAt + GetMaxAge_ ();
110 return now > expiresAt;
112 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
113 constexpr auto TimedCache<KEY, VALUE, TRAITS>::GetMaxAge_ () const -> TimeStampDifferenceType
115 if constexpr (TRAITS::kPerCacheMaxAge) {
119 return TRAITS::kDefaultMaxAge;
122 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
125 if constexpr (TRAITS::kPerCacheMaxAge) {
126 shared_lock critSec{fMaybeMutex_};
127 return GetMaxAge_ ();
130 return TRAITS::kDefaultMaxAge;
133 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
135 requires (TRAITS::kPerCacheMaxAge)
137 Require (maxAge > 0.0s);
138 scoped_lock critSec{fMaybeMutex_};
139 if (fMaxAge_ != maxAge) {
144 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
147 shared_lock critSec{fMaybeMutex_};
148 vector<CacheElement> r;
149 r.reserve (fData_.size ());
150 TimeStampType now = TRAITS::GetCurrentTimestamp ();
151 for (
const auto& i : fData_) {
152 if (not Expired_ (i.second, now)) {
153 r.push_back (i.second.MakeCacheElement (i.first));
158 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
159 template <
typename K>
164 shared_lock critSec{fMaybeMutex_};
165 r.reserve (fData_.size ());
166 TimeStampType now = TRAITS::GetCurrentTimestamp ();
167 for (
const auto& i : fData_) {
168 if (not Expired_ (i.second, now)) {
169 r.push_back (i.first);
172 return Traversal::Iterable<KEY>{move (r)};
174 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
175 template <
typename K,
typename V>
176 requires (IKeyedCache<K> and not IValuelessCache<V>)
177 optional<VALUE> TimedCache<KEY, VALUE, TRAITS>::Lookup (
typename Common::ArgByValueType<K> key)
const
179 shared_lock critSec{fMaybeMutex_};
180 typename MyMapType_::const_iterator i = fData_.find (key);
181 if (i == fData_.end ()) {
182 fStats_.IncrementMisses ();
186 if (Expired_ (i->second)) {
190 fStats_.IncrementMisses ();
193 fStats_.IncrementHits ();
194 return i->second.fResult;
197 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
198 template <
typename K,
typename V>
199 requires (IKeyedCache<K> and not IValuelessCache<V>)
200 optional<VALUE> TimedCache<KEY, VALUE, TRAITS>::Lookup (
typename Common::ArgByValueType<K> key)
202 shared_lock critSec{fMaybeMutex_};
203 typename MyMapType_::iterator i = fData_.find (key);
204 if (i == fData_.end ()) {
205 fStats_.IncrementMisses ();
209 if (Expired_ (i->second)) {
213 (void)fData_.erase (i);
214 fStats_.IncrementMisses ();
218 if constexpr (TRAITS::kAutomaticallyMarkDataAsRefreshedEachTimeAccessed) {
219 i->second.fLastRefreshedAt = TRAITS::GetCurrentTimestamp ();
221 fStats_.IncrementHits ();
222 return i->second.fResult;
225 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
226 template <
typename K>
227 requires (IKeyedCache<K> and TRAITS::kTrackFreshness)
228 optional<VALUE> TimedCache<KEY, VALUE, TRAITS>::Lookup (
typename Common::ArgByValueType<K> key, TimeStampDifferenceType maxAge)
const
230 shared_lock critSec{fMaybeMutex_};
231 typename MyMapType_::const_iterator i = fData_.find (key);
232 TimeStampType now = TRAITS::GetCurrentTimestamp ();
233 if (i == fData_.end ()) {
234 fStats_.IncrementMisses ();
238 if (i->second.fLastRefreshedAt + maxAge <= now) {
242 fStats_.IncrementMisses ();
245 fStats_.IncrementHits ();
246 return i->second.fResult;
249 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
250 template <
typename K>
251 requires (not IKeyedCache<K>)
252 optional<VALUE> TimedCache<KEY, VALUE, TRAITS>::Lookup ()
const
254 shared_lock critSec{fMaybeMutex_};
255 if (optional<VALUE> ov = fData_) {
256 if (Expired_ (*ov)) {
260 fStats_.IncrementMisses ();
263 fStats_.IncrementHits ();
268 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
269 template <
typename K>
270 requires (not IKeyedCache<K>)
271 optional<VALUE> TimedCache<KEY, VALUE, TRAITS>::Lookup ()
273 scoped_lock critSec{fMaybeMutex_};
274 if (optional<VALUE> ov = fData_) {
275 if (Expired_ (*ov)) {
280 fStats_.IncrementMisses ();
283 fStats_.IncrementHits ();
288 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
289 template <
typename K>
290 requires (not IKeyedCache<K> and TRAITS::kTrackFreshness)
291 inline optional<VALUE> TimedCache<KEY, VALUE, TRAITS>::Lookup (TimeStampDifferenceType maxAge)
const
293 if (optional<MyResult_> ov = fData_) {
294 TimeStampType now = TRAITS::GetCurrentTimestamp ();
295 if (ov->fLastRefreshedAt + maxAge <= now) {
299 fStats_.IncrementMisses ();
302 fStats_.IncrementHits ();
307 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
308 template <
typename K,
typename V>
309 requires (IKeyedCache<K> and IValuelessCache<V>)
310 optional<KEY> TimedCache<KEY, VALUE, TRAITS>::Lookup (
typename Common::ArgByValueType<K> key)
const
312 shared_lock critSec{fMaybeMutex_};
313 typename MyMapType_::const_iterator i = fData_.find (key);
314 if (i == fData_.end ()) {
315 fStats_.IncrementMisses ();
319 if (Expired_ (i->second)) {
323 fStats_.IncrementMisses ();
326 fStats_.IncrementHits ();
331 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
332 template <
typename K>
334 requires (kTrackExpiration and IKeyedCache<K>)
336 shared_lock critSec{fMaybeMutex_};
337 typename MyMapType_::const_iterator i = fData_.find (key);
338 if (i == fData_.end ()) {
339 fStats_.IncrementMisses ();
343 if (Expired_ (i->second)) {
347 fStats_.IncrementMisses ();
350 fStats_.IncrementHits ();
351 return make_tuple (i->second.fResult, i->second.fExpiresAt);
354 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
355 template <
typename K>
357 requires (kTrackExpiration and IKeyedCache<K>)
359 shared_lock critSec{fMaybeMutex_};
360 typename MyMapType_::iterator i = fData_.find (key);
361 if (i == fData_.end ()) {
362 fStats_.IncrementMisses ();
366 if (Expired_ (i->second)) {
370 (void)fData_.erase (i);
371 fStats_.IncrementMisses ();
374 fStats_.IncrementHits ();
375 return make_tuple (i->second.fResult, i->second.fExpiresAt);
378 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
379 template <
typename K>
381 requires (kTrackFreshness and IKeyedCache<K>)
383 shared_lock critSec{fMaybeMutex_};
384 typename MyMapType_::const_iterator i = fData_.find (key);
385 if (i == fData_.end ()) {
386 fStats_.IncrementMisses ();
390 if (Expired_ (i->second)) {
394 fStats_.IncrementMisses ();
397 fStats_.IncrementHits ();
398 return make_tuple (i->second.fResult, i->second.fLastRefreshedAt);
401 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
402 template <
typename K>
404 requires (kTrackFreshness and IKeyedCache<K>)
406 shared_lock critSec{fMaybeMutex_};
407 typename MyMapType_::iterator i = fData_.find (key);
408 if (i == fData_.end ()) {
409 fStats_.IncrementMisses ();
413 if (Expired_ (i->second)) {
417 (void)fData_.erase (i);
418 fStats_.IncrementMisses ();
422 if constexpr (TRAITS::kAutomaticallyMarkDataAsRefreshedEachTimeAccessed) {
423 i->second.fLastRefreshedAt = TRAITS::GetCurrentTimestamp ();
425 fStats_.IncrementHits ();
426 return make_tuple (i->second.fResult, i->second.fLastRefreshedAt);
429 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
430 template <
typename K>
432 -> optional<tuple<VALUE, TimeStampType>>
433 requires (kTrackFreshness and IKeyedCache<K>)
435 shared_lock critSec{fMaybeMutex_};
436 typename MyMapType_::const_iterator i = fData_.find (key);
437 TimeStampType now = TRAITS::GetCurrentTimestamp ();
438 if (i == fData_.end ()) {
439 fStats_.IncrementMisses ();
443 if (i->second.fLastRefreshedAt + maxAge <= now) {
447 fStats_.IncrementMisses ();
450 fStats_.IncrementHits ();
451 return make_tuple (i->second.fResult, i->second.fLastRefreshedAt);
454 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
455 template <
typename K>
457 requires (not IKeyedCache<K>)
462 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
463 template <
typename K,
typename V>
464 requires (IKeyedCache<K> and IValuelessCache<V>)
467 static_assert (not IKeyedCache<KEY>);
468 shared_lock critSec{fMaybeMutex_};
469 typename MyMapType_::const_iterator i = fData_.find (key);
470 if (i == fData_.end ()) {
471 fStats_.IncrementMisses ();
475 if (Expired_ (i->second)) {
479 fStats_.IncrementMisses ();
482 fStats_.IncrementHits ();
487 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
488 template <
typename K>
492 if (optional<MyResult_> ov = fData_) {
493 if (Expired_ (*ov)) {
497 fStats_.IncrementMisses ();
500 fStats_.IncrementHits ();
505 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
506 template <
typename K>
508 requires (IKeyedCache<K>)
510 typename MyMapType_::const_iterator i = fData_.find (key);
511 if (i == fData_.end ()) {
514 if (Expired_ (i->second)) {
517 if constexpr (kTrackExpiration) {
518 return i->second.fExpiresAt;
520 else if constexpr (kTrackFreshness) {
521 return i->second.fLastRefreshedAt + GetMaxAge_ ();
524 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
525 template <
typename K, Common::invocable_r<VALUE, KEY> CACHE_FILLTER_T>
526 requires (IKeyedCache<K>)
529 if (optional<VALUE> o = Lookup (key)) {
533 return LockingLookupValueAdder_ (key, forward<CACHE_FILLTER_T> (cacheFiller));
536 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
537 template <
typename K, Common::invocable_r<VALUE, KEY> CACHE_FILLTER_T>
538 requires (IKeyedCache<K> and TRAITS::kTrackFreshness)
541 if (optional<VALUE> o = Lookup (key, maxAge)) {
545 return LockingLookupValueAdder_ (key, forward<CACHE_FILLTER_T> (cacheFiller));
548 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
549 template <
typename K, Common::invocable_r<VALUE> CACHE_FILLTER_T>
550 requires (not IKeyedCache<K>)
553 if (optional<VALUE> ov = Lookup ()) {
557 return LockingLookupValueAdder_ (forward<CACHE_FILLTER_T> (cacheFiller));
560 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
561 template <
typename K, Common::invocable_r<VALUE> CACHE_FILLTER_T>
562 requires (not IKeyedCache<K> and TRAITS::kTrackFreshness)
565 if (optional<VALUE> ov = Lookup (maxAge)) {
569 return LockingLookupValueAdder_ (forward<CACHE_FILLTER_T> (cacheFiller));
572 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
573 template <
typename K,
typename V, Common::invocable_r<K, K> CACHE_FILLTER_T>
574 requires (IKeyedCache<K> and IValuelessCache<V>)
577 if (optional<KEY> ok = Lookup (key)) {
581 KEY kr = forward<CACHE_FILLTER_T> (cacheFiller) (key);
586 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
587 template <
typename K, Common::invocable_r<VALUE> CACHE_FILLTER_T>
588 requires (not IKeyedCache<K>)
589 inline VALUE TimedCache<KEY, VALUE, TRAITS>::LockingLookupValueAdder_ (CACHE_FILLTER_T&& cacheFiller)
591 VALUE r = forward<CACHE_FILLTER_T> (cacheFiller) ();
595 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
596 template <
typename K, Common::invocable_r<VALUE, KEY> CACHE_FILLTER_T>
597 requires (IKeyedCache<K>)
598 inline VALUE TimedCache<KEY, VALUE, TRAITS>::LockingLookupValueAdder_ (
typename Common::ArgByValueType<K> key, CACHE_FILLTER_T&& cacheFiller)
600 if constexpr (TRAITS::kHoldWriteLockDuringCacheFill) {
601 scoped_lock critSec{fMaybeMutex_};
602 VALUE v = forward<CACHE_FILLTER_T> (cacheFiller) (key);
603 AutomaticallyClearExpiredDataSometimes_ ();
608 VALUE v = forward<CACHE_FILLTER_T> (cacheFiller) (key);
613 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
614 template <
typename K>
615 requires (IKeyedCache<K> and IValuelessCache<VALUE>)
618 scoped_lock critSec{fMaybeMutex_};
620 TimeStampType now = TRAITS::GetCurrentTimestamp ();
621 if constexpr (kTrackExpiration) {
622 Add_ (key, now + GetMaxAge_ ());
624 else if constexpr (kTrackFreshness) {
628 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
629 template <
typename K,
typename V>
630 requires (IKeyedCache<K> and not IValuelessCache<V>)
633 scoped_lock critSec{fMaybeMutex_};
634 AutomaticallyClearExpiredDataSometimes_ ();
635 TimeStampType now = TRAITS::GetCurrentTimestamp ();
636 if constexpr (kTrackExpiration) {
637 Add_ (key, result, now + GetMaxAge_ ());
639 else if constexpr (kTrackFreshness) {
640 Add_ (key, result, now);
643 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
644 template <
typename K,
typename V>
645 requires (IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackFreshness)
648 scoped_lock critSec{fMaybeMutex_};
649 AutomaticallyClearExpiredDataSometimes_ ();
650 Add_ (key, result, freshAsOf);
652 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
653 template <
typename K,
typename V>
654 requires (IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackExpiration)
657 scoped_lock critSec{fMaybeMutex_};
658 AutomaticallyClearExpiredDataSometimes_ ();
659 Add_ (key, result, expiresAt);
661 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
662 template <
typename K,
typename V>
663 requires (not IKeyedCache<K> and not IValuelessCache<V>)
666 TimeStampType now = TRAITS::GetCurrentTimestamp ();
667 if constexpr (kTrackExpiration) {
668 Add (result, now + GetMaxAge_ ());
670 else if constexpr (kTrackFreshness) {
674 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
675 template <
typename K,
typename V>
676 requires (not IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackFreshness)
679 scoped_lock critSec{fMaybeMutex_};
681 Add_ (result, freshAsOf);
683 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
684 template <
typename K,
typename V>
685 requires (not IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackExpiration)
688 scoped_lock critSec{fMaybeMutex_};
689 AutomaticallyClearExpiredDataSometimes_ ();
690 Add_ (result, expiresAt);
692 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
693 template <
typename K>
694 requires (IKeyedCache<K> and IValuelessCache<VALUE> and TRAITS::kTrackExpiration)
695 inline void TimedCache<KEY, VALUE, TRAITS>::Add_ (
typename Common::ArgByValueType<K> key, TimeStampType expiresAt)
697 fData_.insert_or_assign (key, MyResult_{.fExpiresAt = expiresAt});
699 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
700 template <
typename K>
701 requires (IKeyedCache<K> and IValuelessCache<VALUE> and TRAITS::kTrackFreshness)
702 inline void TimedCache<KEY, VALUE, TRAITS>::Add_ (
typename Common::ArgByValueType<K> key, TimeStampType freshAsOf)
704 fData_.insert_or_assign (key, MyResult_{.fLastRefreshedAt = freshAsOf});
706 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
707 template <
typename K,
typename V>
708 requires (IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackFreshness)
709 inline void TimedCache<KEY, VALUE, TRAITS>::Add_ (
typename Common::ArgByValueType<K> key,
typename Common::ArgByValueType<V> result, TimeStampType freshAsOf)
711 fData_.insert_or_assign (key, MyResult_{.fResult = result, .fLastRefreshedAt = freshAsOf});
713 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
714 template <
typename K,
typename V>
715 requires (IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackExpiration)
716 inline void TimedCache<KEY, VALUE, TRAITS>::Add_ (
typename Common::ArgByValueType<K> key,
typename Common::ArgByValueType<V> result, TimeStampType expiresAt)
718 fData_.insert_or_assign (key, MyResult_{.fResult = result, .fExpiresAt = expiresAt});
720 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
721 template <
typename K,
typename V>
722 requires (not IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackFreshness)
723 inline void TimedCache<KEY, VALUE, TRAITS>::Add_ (
typename Common::ArgByValueType<V> result, TimeStampType freshAsOf)
725 fData_ = MyResult_{.fResult = result, .fLastRefreshedAt = freshAsOf};
727 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
728 template <
typename K,
typename V>
729 requires (not IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackExpiration)
730 inline void TimedCache<KEY, VALUE, TRAITS>::Add_ (
typename Common::ArgByValueType<V> result, TimeStampType expiresAt)
732 fData_ = MyResult_{.fResult = result, .fExpiresAt = expiresAt};
734 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
735 template <
typename K>
736 requires (IKeyedCache<K>)
737 inline void TimedCache<KEY, VALUE, TRAITS>::Remove (
typename Common::ArgByValueType<K> key)
739 scoped_lock critSec{fMaybeMutex_};
741 AutomaticallyClearExpiredDataSometimes_ ();
743 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
744 template <qCompilerAndStdLib_Constra
intDiffersInTemplateRedeclaration_BWA (predicate<
typename TimedCache<KEY, VALUE, TRAITS>::CacheElement>) PREDICATE>
745 void TimedCache<KEY, VALUE, TRAITS>::RemoveAll (PREDICATE&& p)
747 scoped_lock critSec{fMaybeMutex_};
748 for (
auto i = fData_.begin (); i != fData_.end ();) {
749 if (p (i->second.MakeCacheElement (i->first))) {
750 i = fData_.erase (i);
757 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
758 template <Traversal::IIterableOfTo<KEY> ITERABLE_OF_KEY_TYPE>
761 scoped_lock critSec{fMaybeMutex_};
763 Containers::Mapping<KEY, MyResult_> tmp{this->fData_};
764 tmp.RetainAll (items);
765 fData_ = tmp.template As<MyMapType_> ();
767 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
770 scoped_lock critSec{fMaybeMutex_};
773 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
776 scoped_lock critSec{fMaybeMutex_};
779 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
781 requires (TRAITS::kTrackFreshness)
783 scoped_lock critSec{fMaybeMutex_};
784 ClearExpired_ (maxAge);
786 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
787 inline typename TRAITS::StatsType TimedCache<KEY, VALUE, TRAITS>::GetStats ()
const
791 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
792 inline void TimedCache<KEY, VALUE, TRAITS>::AutomaticallyClearExpiredDataSometimes_ ()
793 requires (IKeyedCache<KEY>)
797 if (fNextAutoClearAt_ < TRAITS::GetCurrentTimestamp ()) [[unlikely]] {
799 WeakAssert (fNextAutoClearAt_ > TRAITS::GetCurrentTimestamp ());
804 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
805 void TimedCache<KEY, VALUE, TRAITS>::ClearExpired_ ()
806 requires (IKeyedCache<KEY>)
808 TimeStampType now = TRAITS::GetCurrentTimestamp ();
809 for (
typename MyMapType_::iterator i = fData_.begin (); i != fData_.end ();) {
810 if (Expired_ (i->second, now)) {
811 i = fData_.erase (i);
818 fNextAutoClearAt_ = now + TRAITS::kAutomaticPurgeFrequency;
821 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
822 void TimedCache<KEY, VALUE, TRAITS>::ClearExpired_ (TimeStampDifferenceType maxAge)
823 requires (IKeyedCache<KEY> and TRAITS::kTrackFreshness)
825 TimeStampType now = TRAITS::GetCurrentTimestamp ();
826 for (
typename MyMapType_::iterator i = fData_.begin (); i != fData_.end ();) {
827 if (i->second.fLastRefreshedAt + maxAge <= now) {
828 i = fData_.erase (i);
835 fNextAutoClearAt_ = now + TRAITS::kAutomaticPurgeFrequency;
842 template <
typename KEY,
typename VALUE,
typename TIME_TRAITS = TimedCacheSupport::DefaultTraits<KEY, VALUE>>
843 class [[deprecated (
"Since Stroika v3.0d23 - TimedCache has the same functionality and mostly the same names")]] CallerStalenessCache
844 :
public TimedCache<KEY, VALUE, TimedCacheSupport::DefaultTraits<KEY, VALUE>> {
846 using inherited = TimedCache<KEY, VALUE, TimedCacheSupport::DefaultTraits<KEY, VALUE>>;
849 using TraitsType =
typename inherited::TraitsType;
850 using TimeStampType =
typename inherited::TimeStampType;
851 using TimeStampDifferenceType =
typename inherited::TimeStampDifferenceType;
854 [[deprecated (
"Since Stroika v3.0d23, usually just get rid of call and argument can be used directly in situ")]]
855 static TimeStampType Ago (TimeStampDifferenceType backThisTime)
857 Require (backThisTime >= 0s);
858 return TraitsType::GetCurrentTimestamp () - backThisTime;
860 [[deprecated (
"Since Stroika v3.0d23, use TraitsType::GetCurrentStamp")]]
861 static TimeStampType GetCurrentTimestamp ()
863 return TraitsType::GetCurrentTimestamp ();
866 template <
typename KEY,
typename VALUE,
typename TIME_TRAITS = TimedCacheSupport::DefaultTraits<KEY, VALUE>>
867 class [[deprecated (
"Since Stroika v3.0d23 - TimedCache (or SyncrhonizedTimedCache) has the same functionality and mostly the same "
868 "names")]] SynchronizedCallerStalenessCache
869 :
public TimedCache<KEY, VALUE, TimedCacheSupport::InternallySynchronizedTraits<TimedCacheSupport::DefaultTraits<KEY, VALUE>>> {
871 using inherited = TimedCache<KEY, VALUE, TimedCacheSupport::InternallySynchronizedTraits<TimedCacheSupport::DefaultTraits<KEY, VALUE>>>;
874 using TraitsType =
typename inherited::TraitsType;
875 using TimeStampType =
typename inherited::TimeStampType;
876 using TimeStampDifferenceType =
typename inherited::TimeStampDifferenceType;
879 [[deprecated (
"Since Stroika v3.0d23, usually just get rid of call and argument can be used directly in situ")]]
880 static TimeStampType Ago (TimeStampDifferenceType backThisTime)
882 Require (backThisTime >= 0s);
883 return TraitsType::GetCurrentTimestamp () - backThisTime;
885 [[deprecated (
"Since Stroika v3.0d23, use TraitsType::GetCurrentStamp")]]
886 static TimeStampType GetCurrentTimestamp ()
888 return TraitsType::GetCurrentTimestamp ();
#define AssertNotImplemented()
#define WeakAssert(c)
A WeakAssert() is for things that aren't guaranteed to be true, but are overwhelmingly likely to be t...
#define qStroika_ATTRIBUTE_INDETERMINATE
qStroika_ATTRIBUTE_INDETERMINATE is used where you would use a C++ attribute for a variable that is i...
Keep track of a bunch of objects, each with an associated time used to allow data to 'expire'.
nonvirtual VALUE LookupValue(typename Common::ArgByValueType< K > key, CACHE_FILLTER_T &&cacheFiller)
Lookup value, and if missing, fetch it with argument cacheFiller (and add/return its value).
nonvirtual optional< tuple< VALUE, TimeStampType > > LookupDetails(typename Common::ArgByValueType< K > key) const
Returns the value associated with argument 'key' (if IKeyedCache), or nullopt, if its missing (missin...
nonvirtual TimeStampDifferenceType GetMaxAge() const
nonvirtual Traversal::Iterable< K > Keys() const
nonvirtual void SetMaxAge(TimeStampDifferenceType maxAge)
nonvirtual Traversal::Iterable< CacheElement > Elements() const
nonvirtual void ClearExpiredData()
nonvirtual optional< TimeStampType > GetExpiration() const
Get the Expiration of object or nullopt of item expired/not in cache.
nonvirtual void RetainAll(const ITERABLE_OF_KEY_TYPE &items2Keep)
like Mapping<>::RetainAll () - throw away all elements not in items2Keep
nonvirtual void Add(typename Common::ArgByValueType< K > key)
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
constexpr float kNoAutomaticPurgeSentinal
see TimedCache<>::TraitsType::kAutomaticPurgeFrequency - disable automatic purging
static constexpr bool IKeyedCache
Does this cache have a KEY type (overwhelming YES, but sometimes handy to have 'singleton' cache,...
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.
everything here is optional ;-) But typically, its fKey, fValue, fLastRefreshedAt