From f5a5e3245a8cd384d0f6f7e0f25aab3b7b380957 Mon Sep 17 00:00:00 2001 From: Ben Manes Date: Mon, 22 Feb 2021 17:14:41 -0800 Subject: [PATCH] Add putIfAbsent optimistic fastpath (#506) --- build.gradle | 2 +- .../caffeine/cache/BoundedLocalCache.java | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ad3d08bfb6..26107bf36c 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ allprojects { version.with { major = 2 // incompatible API changes minor = 9 // backwards-compatible additions - patch = 0 // backwards-compatible bug fixes + patch = 1 // backwards-compatible bug fixes releaseBuild = rootProject.hasProperty('release') } } diff --git a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java index 9f4826bb1c..38595edf6c 100644 --- a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java +++ b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java @@ -2029,12 +2029,34 @@ public Map getAllPresent(Iterable keys) { if (prior == node) { afterWrite(new AddTask(node, newWeight)); return null; + } else if (onlyIfAbsent) { + // An optimistic fast path to avoid unnecessary locking + V currentValue = prior.getValue(); + if ((currentValue != null) && !hasExpired(prior, now)) { + if (!isComputingAsync(prior)) { + tryExpireAfterRead(prior, key, currentValue, expiry(), now); + setAccessTime(prior, now); + } + afterRead(prior, now, /* recordHit */ false); + return currentValue; + } } } else { prior = data.putIfAbsent(node.getKeyReference(), node); if (prior == null) { afterWrite(new AddTask(node, newWeight)); return null; + } else if (onlyIfAbsent) { + // An optimistic fast path to avoid unnecessary locking + V currentValue = prior.getValue(); + if ((currentValue != null) && !hasExpired(prior, now)) { + if (!isComputingAsync(prior)) { + tryExpireAfterRead(prior, key, currentValue, expiry(), now); + setAccessTime(prior, now); + } + afterRead(prior, now, /* recordHit */ false); + return currentValue; + } } } } else if (onlyIfAbsent) {