putIfAbsent method
Associates the specified key
with the given value
if not already associated with a 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
Returns true
if a value was set.
Implementation
@override
Future<bool> putIfAbsent(String key, T value,
{CacheEntryDelegate<T>? delegate}) {
// Current time
final now = clock.now();
// #region Statistics
Stopwatch? watch;
Future<CacheInfo?> Function(CacheInfo? info) posGet =
(CacheInfo? info) => Future.value(info);
Future<bool> Function(bool ok) posPut = (bool ok) => Future<bool>.value(ok);
if (statsEnabled) {
watch = clock.stopwatch()..start();
posGet = (CacheInfo? info) {
if (info == null || info.isExpired(now)) {
stats.increaseMisses();
} else {
stats.increaseGets();
}
return Future.value(info);
};
posPut = (bool ok) {
if (ok) {
stats.increasePuts();
}
if (watch != null) {
stats.addPutTime(watch.elapsedMicroseconds);
watch.stop();
}
return Future<bool>.value(ok);
};
}
// #endregion
// Try to get the entry from the cache
return _getStorageInfo(key).then(posGet).then((info) {
final expired = info != null && info.isExpired(now);
// If the entry exists on cache but is already expired we remove it first
final pre = expired
? _removeStorageEntry(key, CacheEntryExpiredEvent<T>(this, info))
: Future<void>.value();
// If the entry is expired or non existent
if (info == null || expired) {
return pre
.then((_) =>
_newEntry(_entryBuilder(key, value, now, delegate: delegate)))
.then(posPut);
}
return posPut(false);
});
}