@Override public void put(K key, V value) { requireNonNull(value); asyncCache().cache().put(key, CompletableFuture.completedFuture(value)); }
@Override public void invalidateAll(Iterable<?> keys) { asyncCache().cache().invalidateAll(keys); }
@Override public ConcurrentMap<K, V> asMap() { return (asMapView == null) ? (asMapView = new AsMapView<>(asyncCache().cache())) : asMapView; } }
@Override public void cleanUp() { asyncCache().cache().cleanUp(); }
@Override public void invalidateAll() { asyncCache().cache().clear(); }
@Override public void invalidate(Object key) { asyncCache().cache().remove(key); }
@Override public long estimatedSize() { return asyncCache().cache().size(); }
@SuppressWarnings({"FutureReturnValueIgnored", "NullAway"}) default CompletableFuture<V> get(K key, BiFunction<? super K, Executor, CompletableFuture<V>> mappingFunction, boolean recordStats) { long startTime = cache().statsTicker().read(); @SuppressWarnings({"unchecked", "rawtypes"}) CompletableFuture<V>[] result = new CompletableFuture[1]; CompletableFuture<V> future = cache().computeIfAbsent(key, k -> { result[0] = mappingFunction.apply(key, cache().executor()); return requireNonNull(result[0]); }, recordStats, /* recordLoad */ false); long loadTime = cache().statsTicker().read() - startTime; if (value == null) { if (error != null) { logger.log(Level.WARNING, "Exception thrown during asynchronous load", error); cache().statsCounter().recordLoadFailure(loadTime); cache().remove(key, result[0]); } else { cache().replace(key, result[0], result[0]); cache().statsCounter().recordLoadSuccess(loadTime);
if (valueFuture.isCompletedExceptionally() || (valueFuture.isDone() && (valueFuture.join() == null))) { cache().statsCounter().recordLoadFailure(0L); cache().remove(key); return; long startTime = cache().statsTicker().read(); cache().put(key, valueFuture); valueFuture.whenComplete((value, error) -> { if (!completed.compareAndSet(false, true)) { long loadTime = cache().statsTicker().read() - startTime; if (value == null) { if (error != null) { logger.log(Level.WARNING, "Exception thrown during asynchronous load", error); cache().remove(key, valueFuture); cache().statsCounter().recordLoadFailure(loadTime); } else { cache().replace(key, valueFuture, valueFuture); cache().statsCounter().recordLoadSuccess(loadTime);
@Override public Map<K, V> getAllPresent(Iterable<?> keys) { Set<Object> uniqueKeys = new LinkedHashSet<>(); for (Object key : keys) { uniqueKeys.add(key); } int misses = 0; Map<Object, Object> result = new LinkedHashMap<>(); for (Object key : uniqueKeys) { CompletableFuture<V> future = asyncCache().cache().get(key); Object value = Async.getIfReady(future); if (value == null) { misses++; } else { result.put(key, value); } } asyncCache().cache().statsCounter().recordMisses(misses); asyncCache().cache().statsCounter().recordHits(result.size()); @SuppressWarnings("unchecked") Map<K, V> castedResult = (Map<K, V>) result; return Collections.unmodifiableMap(castedResult); }
@Override public CacheStats stats() { return asyncCache().cache().statsCounter().snapshot(); }
@Override default @Nullable CompletableFuture<V> getIfPresent(@NonNull Object key) { return cache().getIfPresent(key, /* recordStats */ true); }
@Override public @Nullable V getIfPresent(Object key) { CompletableFuture<V> future = asyncCache().cache().getIfPresent(key, /* recordStats */ true); return Async.getIfReady(future); }