Skip to content

Commit b174bdb

Browse files
author
Vincent Potucek
committed
[tryout fix] concurrency bug in NamespacedHierarchicalStore#computeIfAbsent(Object, Object, Function) junit-team#5171 junit-team#5209
Signed-off-by: Vincent Potucek <vpotucek@me.com>
1 parent 116b113 commit b174bdb

File tree

1 file changed

+13
-10
lines changed

1 file changed

+13
-10
lines changed

junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStore.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.function.Supplier;
3131

3232
import org.apiguardian.api.API;
33+
import org.jspecify.annotations.NonNull;
3334
import org.jspecify.annotations.Nullable;
3435
import org.junit.platform.commons.util.Preconditions;
3536
import org.junit.platform.commons.util.UnrecoverableExceptions;
@@ -244,16 +245,10 @@ public <K, V> Object computeIfAbsent(N namespace, K key, Function<? super K, ? e
244245
StoredValue storedValue = getStoredValue(compositeKey);
245246
var result = StoredValue.evaluateIfNotNull(storedValue);
246247
if (result == null) {
247-
var value = storedValues.compute(compositeKey, (__, currentValue) -> {
248-
if (currentValue == null || currentValue.equals(storedValue)) {
249-
rejectIfClosed();
250-
return newStoredValue(new MemoizingSupplier(() -> {
251-
rejectIfClosed();
252-
return requireNonNull(defaultCreator.apply(key));
253-
}));
254-
}
255-
return currentValue;
256-
});
248+
var value = storedValues.compute(compositeKey, (__, currentValue) ->
249+
currentValue != null && !currentValue.equals(storedValue)
250+
? currentValue
251+
: getStoredValue(key, defaultCreator));
257252
try {
258253
return requireNonNull(value.evaluate());
259254
}
@@ -267,6 +262,14 @@ public <K, V> Object computeIfAbsent(N namespace, K key, Function<? super K, ? e
267262
return result;
268263
}
269264

265+
private <K, V> StoredValue getStoredValue(K key, Function<? super K, ? extends V> defaultCreator) {
266+
rejectIfClosed();
267+
return newStoredValue(new MemoizingSupplier(() -> {
268+
rejectIfClosed();
269+
return requireNonNull(defaultCreator.apply(key));
270+
}));
271+
}
272+
270273
/**
271274
* Get the value stored for the supplied namespace and key in this store or
272275
* the parent store, if present, or call the supplied function to compute it

0 commit comments

Comments
 (0)