getAndPut method
Associates the specified value
with the specified key
in this cache,
returning an existing value if one existed. If the cache previously contained
a mapping for the key
, the old value is replaced by the specified value.
key
: key with which the specified value is to be associatedvalue
: value to be associated with the specified keydelegate
: provides the caller a way of changing the CacheEntry before persistence
The previous value is returned, or null
if there was no value
associated with the key
previously.
Implementation
@override
Future<T?> getAndPut(String key, T value, {CacheEntryDelegate<T>? delegate}) {
// Current time
final now = clock.now();
// #region Statistics
Stopwatch? watch;
Future<CacheEntry?> Function(CacheEntry? entry) posGet =
(CacheEntry? entry) => Future.value(entry);
Future<T?> Function(bool ok, T? value) posPut =
(bool ok, T? value) => Future<T?>.value(value);
if (statsEnabled) {
watch = clock.stopwatch()..start();
posGet = (CacheEntry? entry) {
if (entry == null || entry.isExpired(now)) {
stats.increaseMisses();
} else {
stats.increaseGets();
}
if (watch != null) {
stats.addGetTime(watch.elapsedMicroseconds);
}
return Future.value(entry);
};
posPut = (bool ok, T? value) {
if (ok) {
stats.increasePuts();
}
if (watch != null) {
stats.addPutTime(watch.elapsedMicroseconds);
watch.stop();
}
return Future<T?>.value();
};
}
// #endregion
// Try to get the entry from the cache
return _getStorageEntry(key).then(posGet).then((entry) {
final expired = entry != null && entry.isExpired(now);
// If the entry exists on cache but is already expired we remove it first
final pre = expired
? _removeStorageEntry(
key, CacheEntryExpiredEvent<T>(this, entry.info))
: Future.value();
// If the entry is expired or non existent
if (entry == null || expired) {
return pre.then((_) =>
_newEntry(_entryBuilder(key, value, now, delegate: delegate))
.then((bool ok) => posPut(ok, null)));
} else {
return pre
.then((_) => _replaceEntry(entry.info, value, now))
.then((_) => posPut(true, entry.value));
}
});
}