|
16 | 16 | import static org.apiguardian.api.API.Status.EXPERIMENTAL; |
17 | 17 | import static org.apiguardian.api.API.Status.MAINTAINED; |
18 | 18 | import static org.junit.platform.commons.util.ExceptionUtils.throwAsUncheckedException; |
| 19 | +import static org.junit.platform.commons.util.Preconditions.notNull; |
19 | 20 | import static org.junit.platform.commons.util.ReflectionUtils.getWrapperType; |
20 | 21 | import static org.junit.platform.commons.util.ReflectionUtils.isAssignableTo; |
21 | 22 |
|
|
31 | 32 |
|
32 | 33 | import org.apiguardian.api.API; |
33 | 34 | import org.jspecify.annotations.Nullable; |
34 | | -import org.junit.platform.commons.util.Preconditions; |
35 | 35 | import org.junit.platform.commons.util.UnrecoverableExceptions; |
36 | 36 |
|
37 | 37 | /** |
@@ -209,7 +209,7 @@ public void close() { |
209 | 209 | @API(status = DEPRECATED, since = "6.0") |
210 | 210 | public <K, V extends @Nullable Object> @Nullable Object getOrComputeIfAbsent(N namespace, K key, |
211 | 211 | Function<? super K, ? extends V> defaultCreator) { |
212 | | - Preconditions.notNull(defaultCreator, "defaultCreator must not be null"); |
| 212 | + notNull(defaultCreator, "defaultCreator must not be null"); |
213 | 213 | CompositeKey<N> compositeKey = new CompositeKey<>(namespace, key); |
214 | 214 | StoredValue storedValue = getStoredValue(compositeKey); |
215 | 215 | if (storedValue == null) { |
@@ -239,28 +239,36 @@ public void close() { |
239 | 239 | */ |
240 | 240 | @API(status = MAINTAINED, since = "6.0") |
241 | 241 | public <K, V> Object computeIfAbsent(N namespace, K key, Function<? super K, ? extends V> defaultCreator) { |
242 | | - Preconditions.notNull(defaultCreator, "defaultCreator must not be null"); |
243 | | - CompositeKey<N> compositeKey = new CompositeKey<>(namespace, key); |
244 | | - StoredValue storedValue = getStoredValue(compositeKey); |
| 242 | + notNull(defaultCreator, "defaultCreator must not be null"); |
| 243 | + var compositeKey = new CompositeKey<>(namespace, key); |
| 244 | + var storedValue = getStoredValue(compositeKey); |
245 | 245 | var result = StoredValue.evaluateIfNotNull(storedValue); |
246 | 246 | if (result == null) { |
247 | | - StoredValue newStoredValue = this.storedValues.compute(compositeKey, (__, oldStoredValue) -> { |
248 | | - if (StoredValue.evaluateIfNotNull(oldStoredValue) == null) { |
249 | | - rejectIfClosed(); |
250 | | - var computedValue = Preconditions.notNull(defaultCreator.apply(key), |
251 | | - "defaultCreator must not return null"); |
252 | | - return newStoredValue(() -> { |
253 | | - rejectIfClosed(); |
254 | | - return computedValue; |
255 | | - }); |
| 247 | + var value = storedValues.compute(compositeKey, |
| 248 | + (__, currentValue) -> currentValue == null || currentValue.equals(storedValue) |
| 249 | + ? storeNewValue(key, defaultCreator) |
| 250 | + : currentValue); |
| 251 | + try { |
| 252 | + return requireNonNull(value.evaluate()); |
| 253 | + } |
| 254 | + catch (Throwable t) { // remove failed entry to allow retry. |
| 255 | + if (value.equals(storedValues.get(compositeKey))) { |
| 256 | + storedValues.remove(compositeKey, value); |
256 | 257 | } |
257 | | - return oldStoredValue; |
258 | | - }); |
259 | | - return requireNonNull(newStoredValue.evaluate()); |
| 258 | + throw t; |
| 259 | + } |
260 | 260 | } |
261 | 261 | return result; |
262 | 262 | } |
263 | 263 |
|
| 264 | + private <K, V> StoredValue storeNewValue(K key, Function<? super K, ? extends V> defaultCreator) { |
| 265 | + rejectIfClosed(); |
| 266 | + return newStoredValue(new MemoizingSupplier(() -> { |
| 267 | + rejectIfClosed(); |
| 268 | + return requireNonNull(defaultCreator.apply(key)); |
| 269 | + })); |
| 270 | + } |
| 271 | + |
264 | 272 | /** |
265 | 273 | * Get the value stored for the supplied namespace and key in this store or |
266 | 274 | * the parent store, if present, or call the supplied function to compute it |
@@ -388,7 +396,7 @@ private StoredValue newStoredValue(Supplier<@Nullable Object> value) { |
388 | 396 | } |
389 | 397 |
|
390 | 398 | private <T> @Nullable T castToRequiredType(Object key, @Nullable Object value, Class<T> requiredType) { |
391 | | - Preconditions.notNull(requiredType, "requiredType must not be null"); |
| 399 | + notNull(requiredType, "requiredType must not be null"); |
392 | 400 | if (value == null) { |
393 | 401 | return null; |
394 | 402 | } |
@@ -419,8 +427,8 @@ private void rejectIfClosed() { |
419 | 427 | private record CompositeKey<N>(N namespace, Object key) { |
420 | 428 |
|
421 | 429 | CompositeKey { |
422 | | - Preconditions.notNull(namespace, "namespace must not be null"); |
423 | | - Preconditions.notNull(key, "key must not be null"); |
| 430 | + notNull(namespace, "namespace must not be null"); |
| 431 | + notNull(key, "key must not be null"); |
424 | 432 | } |
425 | 433 |
|
426 | 434 | } |
|
0 commit comments