Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Stroika::Foundation::Cache::CallerStalenessCache< KEY, VALUE, TIME_TRAITS > Class Template Reference

#include <CallerStalenessCache.h>

Inheritance diagram for Stroika::Foundation::Cache::CallerStalenessCache< KEY, VALUE, TIME_TRAITS >:
Stroika::Foundation::Cache::SynchronizedCallerStalenessCache< pair< Priority, Stroika::Foundation::Characters::String >, bool > Stroika::Foundation::Cache::SynchronizedCallerStalenessCache< KEY, VALUE, TIME_TRAITS >

Public Member Functions

nonvirtual void Clear ()
 
nonvirtual void Add (Common::ArgByValueType< VALUE > v)
 
nonvirtual optional< VALUELookup (TimeStampType staleIfOlderThan) const
 
nonvirtual VALUE LookupValue (TimeStampType staleIfOlderThan, const function< VALUE()> &cacheFiller)
 
nonvirtual void clear ()
 

Static Public Member Functions

static TimeStampType Ago (TimeStampDifferenceType backThisTime)
 

Detailed Description

template<typename KEY, typename VALUE, typename TIME_TRAITS = CallerStalenessCache_Traits_DEFAULT>
class Stroika::Foundation::Cache::CallerStalenessCache< KEY, VALUE, TIME_TRAITS >

The idea behind this cache is to track when something is added, and that the lookup function can avoid a costly call to compute something if its been recently enough added.

For example, consider a system where memory is stored across a slow bus, and several components need to read data from across that bus. But the different components have different tolerance for staleness (e.g. PID loop needs fresh temperature sensor data but GUI can use more stale data).

This CallerStalenessCache will store when the value is updated, and let the caller either return the value from cache, or fetch it and update the cache if needed.

This differs from other forms of caches in that: o It records the timestamp when a value is last-updated o It doesn't EXPIRE the data ever (except by explicit Clear or ClearOlderThan call) o The lookup caller specifies its tolerance for data staleness, and refreshes the data as needed.

Note
Principal difference between CallerStalenessCache and TimedCache lies in where you specify the max-age for an item: with CallerStalenessCache, its specified on each lookup call (ie with the caller), and with TimedCache, the expiry is stored with each cached item.

Because of this, when you use either of these caches with a KEY=void (essentially to cache a single thing) they become indistinguishable.

N.B. the KEY=void functionality is NYI for TimedCache, so best to use CallerStalenessCache for that, at least for now.

Note
KEY may be 'void' - and if so, the KEY parameter to the various Add/Lookup etc functions - is omitted.
Why take 'valid-since' argument to lookup functions, and not just 'backThisTime' - in other words, why force the use of 'Ago()'. The reason is that in a complex system (say web services) - where the final requester of the data specifies the allowed staleness, you want the 'ago' computation based on ITS time (not the time the lookup happens). This is only approximate too, since it doesn't take into account the latency of the return but its a little closer to accurate.
Example Usage
// no key cache
{
return sCache_.Lookup (sCache_.Ago (allowedStaleness.value_or (30)), []() -> optional<InternetAddress> {
...
return IO::Network::InternetAddress{connection.GET ().GetDataTextInputStream ().ReadAll ().Trim ()};
});
}
optional<InternetAddress> iaddr = LookupExternalInternetAddress_ (); // only invoke connection logic if timed out
LRUCache implements a simple least-recently-used caching strategy, with optional hashing (of keys) to...
Definition LRUCache.h:94
nonvirtual optional< VALUE > Lookup(typename Common::ArgByValueType< KEY > key)
Definition LRUCache.inl:253
Example Usage
// keyed cache
{
try {
return sCache_.LookupValue (value, sCache_.Ago (allowedStaleness.value_or (30)), [=](int v) -> optional<int> {
return v; // typically more expensive computation
});
}
catch (...) {
// NOTE - to NEGATIVELY CACHE failure, you could call sCache_.Add (value, nullopt);
// return null here, or Execution::ReThrow ()
}
}
EXPECT_EQ (MapValue_ (1), 1); // skips 'more expensive computation' if in cache
EXPECT_EQ (MapValue_ (2), 2); // ''
nonvirtual VALUE LookupValue(typename Common::ArgByValueType< KEY > key, const function< VALUE(typename Common::ArgByValueType< KEY >)> &valueFetcher)
Definition LRUCache.inl:302
Example Usage
// using KEY=void (so singleton cache)
unsigned int sCalls1_{0};
{
static CallerStalenessCache<void, optional<int>> sCache_;
return sCache_.LookupValue (sCache_.Ago (allowedStaleness.value_or (30)), [] () -> optional<int> {
++sCalls1_;
return 1;
});
}
Note
Implementation Note - no reason to bother using Debug::AssertExternallySynchronized since uses Mapping, which does that internally.
Thread-Safety C++-Standard-Thread-Safety
See also
TimedCache, SynchronizedCallerStalenessCache

Definition at line 134 of file CallerStalenessCache.h.

Member Function Documentation

◆ Ago()

CallerStalenessCache< KEY, VALUE, TIME_TRAITS >::TimeStampType Stroika::Foundation::Cache::CallerStalenessCache< KEY, VALUE, TIME_TRAITS >::Ago ( TimeStampDifferenceType  backThisTime)
static

Return the timestamp backwards the given timestamp.

Precondition
backThisTime >= 0
Example Usage
if (optional<VALUE> v= cc.Lookup (k, cc.Ago (5)) {
// look key, but throw disregard if older than 5 seconds (from now)
}

Definition at line 29 of file CallerStalenessCache.inl.

◆ Clear()

Clear () – clear all Clear (KEY k) - clear just that key

Definition at line 54 of file CallerStalenessCache.inl.

◆ Add()

This not only adds the association of KEY k to VALUE v, but updates the timestamp associated with k.

Definition at line 71 of file CallerStalenessCache.inl.

◆ Lookup()

optional< VALUE > Stroika::Foundation::Cache::CallerStalenessCache< KEY, VALUE, TIME_TRAITS >::Lookup ( TimeStampType  staleIfOlderThan) const

Usually one will use this as (cache fillter overload): VALUE v = cache.Lookup (key, ts, [this] () -> VALUE {return this->realLookup(key); });

However, the overload returning an optional is occasionally useful, if you don't want to fill the cache but just see if a value is present.

Both the overload with cacheFiller, and defaultValue will update the 'time stored' for the argument key.

Note
Some of these Lookup () methods are not const intentionally - as they DO generally modify the cache; but others are read-only, and are therefore const.
Lookup (,,DEFAULT_VALUE) - doesn't fill in the cache value - so not quite the same as Lookup (...,[] () { return DEFAULT_VALUE; });

Definition at line 84 of file CallerStalenessCache.inl.

◆ LookupValue()

VALUE Stroika::Foundation::Cache::CallerStalenessCache< KEY, VALUE, TIME_TRAITS >::LookupValue ( TimeStampType  staleIfOlderThan,
const function< VALUE()> &  cacheFiller 
)

Lookup the value associated with the given key (or key omitted of KEY type is void) and always return it. In case it was stale (or missing) return the provided defaule value (or cacheFiller computed value).

Definition at line 105 of file CallerStalenessCache.inl.

◆ clear()

Aliases
Clear/RemoveAll ().

Definition at line 140 of file CallerStalenessCache.inl.


The documentation for this class was generated from the following files: