diff --git a/commons/src/main/java/io/gitlab/jfronny/commons/concurrent/ScopedValue.java b/commons/src/main/java/io/gitlab/jfronny/commons/concurrent/ScopedValue.java index 83928e5..03e0845 100644 --- a/commons/src/main/java/io/gitlab/jfronny/commons/concurrent/ScopedValue.java +++ b/commons/src/main/java/io/gitlab/jfronny/commons/concurrent/ScopedValue.java @@ -3,6 +3,7 @@ package io.gitlab.jfronny.commons.concurrent; import java.util.Deque; import java.util.LinkedList; import java.util.NoSuchElementException; +import java.util.Optional; import java.util.concurrent.Callable; import java.util.function.Supplier; @@ -75,8 +76,8 @@ public class ScopedValue { } private static class Carrier { - private Deque value; - private Carrier parent; + private final Deque value; + private final Carrier parent; public Carrier() { this(null); @@ -87,10 +88,18 @@ public class ScopedValue { this.parent = parent; } + private Optional valueIfPresent() { + synchronized (value) { + if (!value.isEmpty()) return Optional.of(value.peek()); + return Optional.empty(); + } + } + public T getValue() { - if (!value.isEmpty()) return value.peek(); - if (parent == null) throw new NoSuchElementException("No value present"); - return parent.getValue(); + return valueIfPresent().orElseGet(() -> { + if (parent == null) throw new NoSuchElementException("No value present"); + return parent.getValue(); + }); } public boolean isPresent() { @@ -100,21 +109,27 @@ public class ScopedValue { } public void setValue(T value) { - this.value.push(value); + synchronized (this.value) { + this.value.push(value); + } } public void clear() { - value.pop(); + synchronized (this.value) { + value.pop(); + } } public T orElse(T other) { - if (!value.isEmpty()) return value.peek(); - if (parent == null) return other; - return parent.orElse(other); + return valueIfPresent().orElseGet(() -> { + if (parent == null) return other; + return parent.orElse(other); + }); } public T orElseThrow(Supplier exceptionSupplier) throws X { - if (!value.isEmpty()) return value.peek(); + Optional v = valueIfPresent(); + if (v.isPresent()) return v.get(); if (parent == null) throw exceptionSupplier.get(); return parent.orElseThrow(exceptionSupplier); }