@@ -223,7 +223,7 @@ public void close() {
223223 rejectIfClosed ();
224224 return defaultCreator .apply (key );
225225 });
226- var storedValue = this . storedValues .compute (compositeKey , //
226+ var storedValue = storedValues .compute (compositeKey , //
227227 (__ , oldStoredValue ) -> {
228228 // guard against race conditions, repeated from getStoredValue
229229 // this filters out failures inserted by computeIfAbsent
@@ -279,14 +279,29 @@ public <K, V> Object computeIfAbsent(N namespace, K key, Function<? super K, ? e
279279 return candidateStoredValue ;
280280 });
281281
282+ // In a race condition either put, getOrComputeIfAbsent, or another
283+ // computeIfAbsent call put a non-null value in the store
284+ if (!candidateStoredValue .equals (storedValue )) {
285+ return requireNonNull (storedValue .evaluate ());
286+ }
282287 // Only the caller that created the candidateStoredValue may run it
283288 // and see the exception.
284- if (candidateStoredValue .equals (storedValue )) {
285- return candidateStoredValue .execute ();
289+ Object newResult = candidateStoredValue .execute ();
290+ // DeferredOptionalValue is quite heavy, replace with lighter container
291+ if (candidateStoredValue .isPresent ()) {
292+ storedValues .computeIfPresent (compositeKey , compareAndPut (storedValue , newStoredValue (newResult )));
286293 }
287- // In a race condition either put, getOrComputeIfAbsent, or another
288- // computeIfAbsent call put a non-null value in the store
289- return requireNonNull (storedValue .evaluate ());
294+ return newResult ;
295+ }
296+
297+ private static <N > BiFunction <CompositeKey <N >, StoredValue , StoredValue > compareAndPut (StoredValue expectedValue ,
298+ StoredValue newValue ) {
299+ return (__ , storedValue ) -> {
300+ if (!expectedValue .equals (storedValue )) {
301+ return storedValue ;
302+ }
303+ return newValue ;
304+ };
290305 }
291306
292307 /**
0 commit comments