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>
176 requires (IKeyedCache<K>)
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>
199 requires (IKeyedCache<K>)
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 static_assert (not IKeyedCache<KEY>);
313 shared_lock critSec{fMaybeMutex_};
314 typename MyMapType_::const_iterator i = fData_.find (key);
315 if (i == fData_.end ()) {
316 fStats_.IncrementMisses ();
324 fStats_.IncrementMisses ();
327 fStats_.IncrementHits ();
332 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
333 template <
typename K>
335 requires (kTrackExpiration and IKeyedCache<K>)
337 shared_lock critSec{fMaybeMutex_};
338 typename MyMapType_::const_iterator i = fData_.find (key);
339 if (i == fData_.end ()) {
340 fStats_.IncrementMisses ();
344 if (Expired_ (i->second)) {
348 fStats_.IncrementMisses ();
351 fStats_.IncrementHits ();
352 return make_tuple (i->second.fResult, i->second.fExpiresAt);
355 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
356 template <
typename K>
358 requires (kTrackExpiration and IKeyedCache<K>)
360 shared_lock critSec{fMaybeMutex_};
361 typename MyMapType_::iterator i = fData_.find (key);
362 if (i == fData_.end ()) {
363 fStats_.IncrementMisses ();
367 if (Expired_ (i->second)) {
371 (void)fData_.erase (i);
372 fStats_.IncrementMisses ();
375 fStats_.IncrementHits ();
376 return make_tuple (i->second.fResult, i->second.fExpiresAt);
379 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
380 template <
typename K>
382 requires (kTrackFreshness and IKeyedCache<K>)
384 shared_lock critSec{fMaybeMutex_};
385 typename MyMapType_::const_iterator i = fData_.find (key);
386 if (i == fData_.end ()) {
387 fStats_.IncrementMisses ();
391 if (Expired_ (i->second)) {
395 fStats_.IncrementMisses ();
398 fStats_.IncrementHits ();
399 return make_tuple (i->second.fResult, i->second.fLastRefreshedAt);
402 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
403 template <
typename K>
405 requires (kTrackFreshness and IKeyedCache<K>)
407 shared_lock critSec{fMaybeMutex_};
408 typename MyMapType_::iterator i = fData_.find (key);
409 if (i == fData_.end ()) {
410 fStats_.IncrementMisses ();
414 if (Expired_ (i->second)) {
418 (void)fData_.erase (i);
419 fStats_.IncrementMisses ();
423 if constexpr (TRAITS::kAutomaticallyMarkDataAsRefreshedEachTimeAccessed) {
424 i->second.fLastRefreshedAt = TRAITS::GetCurrentTimestamp ();
426 fStats_.IncrementHits ();
427 return make_tuple (i->second.fResult, i->second.fLastRefreshedAt);
430 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
431 template <
typename K>
433 -> optional<tuple<VALUE, TimeStampType>>
434 requires (kTrackFreshness and IKeyedCache<K>)
436 shared_lock critSec{fMaybeMutex_};
437 typename MyMapType_::const_iterator i = fData_.find (key);
438 TimeStampType now = TRAITS::GetCurrentTimestamp ();
439 if (i == fData_.end ()) {
440 fStats_.IncrementMisses ();
444 if (i->second.fLastRefreshedAt + maxAge <= now) {
448 fStats_.IncrementMisses ();
451 fStats_.IncrementHits ();
452 return make_tuple (i->second.fResult, i->second.fLastRefreshedAt);
455 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
456 template <
typename K>
458 requires (not IKeyedCache<K>)
463 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
464 template <
typename K,
typename V>
465 requires (IKeyedCache<K> and IValuelessCache<V>)
468 static_assert (not IKeyedCache<KEY>);
469 shared_lock critSec{fMaybeMutex_};
470 typename MyMapType_::const_iterator i = fData_.find (key);
471 if (i == fData_.end ()) {
472 fStats_.IncrementMisses ();
480 fStats_.IncrementMisses ();
483 fStats_.IncrementHits ();
488 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
489 template <
typename K>
493 if (optional<MyResult_> ov = fData_) {
494 if (Expired_ (*ov)) {
498 fStats_.IncrementMisses ();
501 fStats_.IncrementHits ();
506 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
507 template <
typename K>
509 requires (IKeyedCache<K>)
511 typename MyMapType_::const_iterator i = fData_.find (key);
512 if (i == fData_.end ()) {
515 if (Expired_ (i->second)) {
518 if constexpr (kTrackExpiration) {
519 return i->second.fExpiresAt;
521 else if constexpr (kTrackFreshness) {
522 return i->second.fLastRefreshedAt + GetMaxAge_ ();
525 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
526 template <
typename K, Common::invocable_r<VALUE, KEY> CACHE_FILLTER_T>
527 requires (IKeyedCache<K>)
530 if (optional<VALUE> o = Lookup (key)) {
534 return LockingLookupValueAdder_ (key, forward<CACHE_FILLTER_T> (cacheFiller));
537 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
538 template <
typename K, Common::invocable_r<VALUE, KEY> CACHE_FILLTER_T>
539 requires (IKeyedCache<K> and TRAITS::kTrackFreshness)
542 if (optional<VALUE> o = Lookup (key, maxAge)) {
546 return LockingLookupValueAdder_ (key, forward<CACHE_FILLTER_T> (cacheFiller));
549 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
550 template <
typename K, Common::invocable_r<VALUE> CACHE_FILLTER_T>
551 requires (not IKeyedCache<K>)
554 if (optional<VALUE> ov = Lookup ()) {
558 return LockingLookupValueAdder_ (forward<CACHE_FILLTER_T> (cacheFiller));
561 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
562 template <
typename K, Common::invocable_r<VALUE> CACHE_FILLTER_T>
563 requires (not IKeyedCache<K> and TRAITS::kTrackFreshness)
566 if (optional<VALUE> ov = Lookup (maxAge)) {
570 return LockingLookupValueAdder_ (forward<CACHE_FILLTER_T> (cacheFiller));
573 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
574 template <
typename K,
typename V, Common::invocable_r<K, K> CACHE_FILLTER_T>
575 requires (IKeyedCache<K> and IValuelessCache<V>)
578 if (optional<KEY> ok = Lookup (key)) {
582 KEY kr = forward<CACHE_FILLTER_T> (cacheFiller) (key);
587 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
588 template <
typename K, Common::invocable_r<VALUE> CACHE_FILLTER_T>
589 requires (not IKeyedCache<K>)
590 inline VALUE TimedCache<KEY, VALUE, TRAITS>::LockingLookupValueAdder_ (CACHE_FILLTER_T&& cacheFiller)
592 VALUE r = forward<CACHE_FILLTER_T> (cacheFiller) ();
596 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
597 template <
typename K, Common::invocable_r<VALUE, KEY> CACHE_FILLTER_T>
598 requires (IKeyedCache<K>)
599 inline VALUE TimedCache<KEY, VALUE, TRAITS>::LockingLookupValueAdder_ (
typename Common::ArgByValueType<K> key, CACHE_FILLTER_T&& cacheFiller)
601 if constexpr (TRAITS::kHoldWriteLockDuringCacheFill) {
602 scoped_lock critSec{fMaybeMutex_};
603 VALUE v = forward<CACHE_FILLTER_T> (cacheFiller) (key);
604 AutomaticallyClearExpiredDataSometimes_ ();
609 VALUE v = forward<CACHE_FILLTER_T> (cacheFiller) (key);
614 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
615 template <
typename K>
616 requires (IKeyedCache<K> and IValuelessCache<VALUE>)
619 scoped_lock critSec{fMaybeMutex_};
621 TimeStampType now = TRAITS::GetCurrentTimestamp ();
622 if constexpr (kTrackExpiration) {
623 Add_ (key, now + GetMaxAge_ ());
625 else if constexpr (kTrackFreshness) {
629 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
630 template <
typename K,
typename V>
631 requires (IKeyedCache<K> and not IValuelessCache<V>)
634 scoped_lock critSec{fMaybeMutex_};
635 AutomaticallyClearExpiredDataSometimes_ ();
636 TimeStampType now = TRAITS::GetCurrentTimestamp ();
637 if constexpr (kTrackExpiration) {
638 Add_ (key, result, now + GetMaxAge_ ());
640 else if constexpr (kTrackFreshness) {
641 Add_ (key, result, now);
644 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
645 template <
typename K,
typename V>
646 requires (IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackFreshness)
649 scoped_lock critSec{fMaybeMutex_};
650 AutomaticallyClearExpiredDataSometimes_ ();
651 Add_ (key, result, freshAsOf);
653 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
654 template <
typename K,
typename V>
655 requires (IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackExpiration)
658 scoped_lock critSec{fMaybeMutex_};
659 AutomaticallyClearExpiredDataSometimes_ ();
660 Add_ (key, result, expiresAt);
662 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
663 template <
typename K,
typename V>
664 requires (not IKeyedCache<K> and not IValuelessCache<V>)
667 TimeStampType now = TRAITS::GetCurrentTimestamp ();
668 if constexpr (kTrackExpiration) {
669 Add (result, now + GetMaxAge_ ());
671 else if constexpr (kTrackFreshness) {
675 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
676 template <
typename K,
typename V>
677 requires (not IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackFreshness)
680 scoped_lock critSec{fMaybeMutex_};
682 Add_ (result, freshAsOf);
684 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
685 template <
typename K,
typename V>
686 requires (not IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackExpiration)
689 scoped_lock critSec{fMaybeMutex_};
690 AutomaticallyClearExpiredDataSometimes_ ();
691 Add_ (result, expiresAt);
693 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
694 template <
typename K>
695 requires (IKeyedCache<K> and IValuelessCache<VALUE> and TRAITS::kTrackExpiration)
696 inline void TimedCache<KEY, VALUE, TRAITS>::Add_ (
typename Common::ArgByValueType<K> key, TimeStampType expiresAt)
698 fData_.insert_or_assign (key, MyResult_{.fExpiresAt = expiresAt});
700 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
701 template <
typename K>
702 requires (IKeyedCache<K> and IValuelessCache<VALUE> and TRAITS::kTrackFreshness)
703 inline void TimedCache<KEY, VALUE, TRAITS>::Add_ (
typename Common::ArgByValueType<K> key, TimeStampType freshAsOf)
705 fData_.insert_or_assign (key, MyResult_{.fLastRefreshedAt = freshAsOf});
707 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
708 template <
typename K,
typename V>
709 requires (IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackFreshness)
710 inline void TimedCache<KEY, VALUE, TRAITS>::Add_ (
typename Common::ArgByValueType<K> key,
typename Common::ArgByValueType<V> result, TimeStampType freshAsOf)
712 fData_.insert_or_assign (key, MyResult_{.fResult = result, .fLastRefreshedAt = freshAsOf});
714 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
715 template <
typename K,
typename V>
716 requires (IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackExpiration)
717 inline void TimedCache<KEY, VALUE, TRAITS>::Add_ (
typename Common::ArgByValueType<K> key,
typename Common::ArgByValueType<V> result, TimeStampType expiresAt)
719 fData_.insert_or_assign (key, MyResult_{.fResult = result, .fExpiresAt = expiresAt});
721 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
722 template <
typename K,
typename V>
723 requires (not IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackFreshness)
724 inline void TimedCache<KEY, VALUE, TRAITS>::Add_ (
typename Common::ArgByValueType<V> result, TimeStampType freshAsOf)
726 fData_ = MyResult_{.fResult = result, .fLastRefreshedAt = freshAsOf};
728 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
729 template <
typename K,
typename V>
730 requires (not IKeyedCache<K> and not IValuelessCache<V> and TRAITS::kTrackExpiration)
731 inline void TimedCache<KEY, VALUE, TRAITS>::Add_ (
typename Common::ArgByValueType<V> result, TimeStampType expiresAt)
733 fData_ = MyResult_{.fResult = result, .fExpiresAt = expiresAt};
735 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
736 template <
typename K>
737 requires (IKeyedCache<K>)
738 inline void TimedCache<KEY, VALUE, TRAITS>::Remove (
typename Common::ArgByValueType<K> key)
740 scoped_lock critSec{fMaybeMutex_};
742 AutomaticallyClearExpiredDataSometimes_ ();
744 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
745 template <qCompilerAndStdLib_Constra
intDiffersInTemplateRedeclaration_BWA (predicate<
typename TimedCache<KEY, VALUE, TRAITS>::CacheElement>) PREDICATE>
746 void TimedCache<KEY, VALUE, TRAITS>::RemoveAll (PREDICATE&& p)
748 scoped_lock critSec{fMaybeMutex_};
749 for (
auto i = fData_.begin (); i != fData_.end ();) {
750 if (p (i->second.MakeCacheElement (i->first))) {
751 i = fData_.erase (i);
758 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
759 template <Traversal::IIterableOfTo<KEY> ITERABLE_OF_KEY_TYPE>
762 scoped_lock critSec{fMaybeMutex_};
764 Containers::Mapping<KEY, MyResult_> tmp{this->fData_};
765 tmp.RetainAll (items);
766 fData_ = tmp.template As<MyMapType_> ();
768 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
771 scoped_lock critSec{fMaybeMutex_};
774 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
777 scoped_lock critSec{fMaybeMutex_};
780 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
782 requires (TRAITS::kTrackFreshness)
784 scoped_lock critSec{fMaybeMutex_};
785 ClearExpired_ (maxAge);
787 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
788 inline typename TRAITS::StatsType TimedCache<KEY, VALUE, TRAITS>::GetStats ()
const
792 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
793 inline void TimedCache<KEY, VALUE, TRAITS>::AutomaticallyClearExpiredDataSometimes_ ()
794 requires (IKeyedCache<KEY>)
798 if (fNextAutoClearAt_ < TRAITS::GetCurrentTimestamp ()) [[unlikely]] {
800 WeakAssert (fNextAutoClearAt_ > TRAITS::GetCurrentTimestamp ());
805 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
806 void TimedCache<KEY, VALUE, TRAITS>::ClearExpired_ ()
807 requires (IKeyedCache<KEY>)
809 TimeStampType now = TRAITS::GetCurrentTimestamp ();
810 for (
typename MyMapType_::iterator i = fData_.begin (); i != fData_.end ();) {
811 if (Expired_ (i->second, now)) {
812 i = fData_.erase (i);
819 fNextAutoClearAt_ = now + TRAITS::kAutomaticPurgeFrequency;
822 template <IKey KEY, IValue VALUE, TimedCacheSupport::ITraits<KEY, VALUE> TRAITS>
823 void TimedCache<KEY, VALUE, TRAITS>::ClearExpired_ (TimeStampDifferenceType maxAge)
824 requires (IKeyedCache<KEY> and TRAITS::kTrackFreshness)
826 TimeStampType now = TRAITS::GetCurrentTimestamp ();
827 for (
typename MyMapType_::iterator i = fData_.begin (); i != fData_.end ();) {
828 if (i->second.fLastRefreshedAt + maxAge <= now) {
829 i = fData_.erase (i);
836 fNextAutoClearAt_ = now + TRAITS::kAutomaticPurgeFrequency;
843 template <
typename KEY,
typename VALUE,
typename TIME_TRAITS = TimedCacheSupport::DefaultTraits<KEY, VALUE>>
844 class [[deprecated (
"Since Stroika v3.0d23 - TimedCache has the same functionality and mostly the same names")]] CallerStalenessCache
845 :
public TimedCache<KEY, VALUE, TimedCacheSupport::DefaultTraits<KEY, VALUE>> {
847 using inherited = TimedCache<KEY, VALUE, TimedCacheSupport::DefaultTraits<KEY, VALUE>>;
850 using TraitsType =
typename inherited::TraitsType;
851 using TimeStampType =
typename inherited::TimeStampType;
852 using TimeStampDifferenceType =
typename inherited::TimeStampDifferenceType;
855 [[deprecated (
"Since Stroika v3.0d23, usually just get rid of call and argument can be used directly in situ")]]
856 static TimeStampType Ago (TimeStampDifferenceType backThisTime)
858 Require (backThisTime >= 0s);
859 return TraitsType::GetCurrentTimestamp () - backThisTime;
861 [[deprecated (
"Since Stroika v3.0d23, use TraitsType::GetCurrentStamp")]]
862 static TimeStampType GetCurrentTimestamp ()
864 return TraitsType::GetCurrentTimestamp ();
867 template <
typename KEY,
typename VALUE,
typename TIME_TRAITS = TimedCacheSupport::DefaultTraits<KEY, VALUE>>
868 class [[deprecated (
"Since Stroika v3.0d23 - TimedCache (or SyncrhonizedTimedCache) has the same functionality and mostly the same "
869 "names")]] SynchronizedCallerStalenessCache
870 :
public TimedCache<KEY, VALUE, TimedCacheSupport::InternallySynchronizedTraits<TimedCacheSupport::DefaultTraits<KEY, VALUE>>> {
872 using inherited = TimedCache<KEY, VALUE, TimedCacheSupport::InternallySynchronizedTraits<TimedCacheSupport::DefaultTraits<KEY, VALUE>>>;
875 using TraitsType =
typename inherited::TraitsType;
876 using TimeStampType =
typename inherited::TimeStampType;
877 using TimeStampDifferenceType =
typename inherited::TimeStampDifferenceType;
880 [[deprecated (
"Since Stroika v3.0d23, usually just get rid of call and argument can be used directly in situ")]]
881 static TimeStampType Ago (TimeStampDifferenceType backThisTime)
883 Require (backThisTime >= 0s);
884 return TraitsType::GetCurrentTimestamp () - backThisTime;
886 [[deprecated (
"Since Stroika v3.0d23, use TraitsType::GetCurrentStamp")]]
887 static TimeStampType GetCurrentTimestamp ()
889 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