feat(commons): Implement fake ScopedValue for use until the real thing arrives
ci/woodpecker/push/woodpecker Pipeline was successful
Details
ci/woodpecker/push/woodpecker Pipeline was successful
Details
This commit is contained in:
parent
fea0d4cc66
commit
3d3c657497
|
@ -0,0 +1,122 @@
|
|||
package io.gitlab.jfronny.commons.concurrent;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Naive, inefficient reimplementation of JDK22 ScopedValue based on ThreadLocal.
|
||||
* See the official Javadoc for more information.
|
||||
* Use the JDK22 version if possible!
|
||||
* Does not include ScopedValue.where
|
||||
*
|
||||
* @param <T> The type of the value
|
||||
*/
|
||||
public class ScopedValue<T> {
|
||||
public static <T> ScopedValue<T> newInstance() {
|
||||
return new ScopedValue<>();
|
||||
}
|
||||
|
||||
public static <T, R> R callWhere(ScopedValue<T> key, T value, Callable<? extends R> op) throws Exception {
|
||||
key.value.get().setValue(value);
|
||||
try {
|
||||
return op.call();
|
||||
} finally {
|
||||
key.value.get().clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static <T, R> R getWhere(ScopedValue<T> key, T value, Supplier<? extends R> op) {
|
||||
key.value.get().setValue(value);
|
||||
try {
|
||||
return op.get();
|
||||
} finally {
|
||||
key.value.get().clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void runWhere(ScopedValue<T> key, T value, Runnable op) {
|
||||
key.value.get().setValue(value);
|
||||
try {
|
||||
op.run();
|
||||
} finally {
|
||||
key.value.get().clear();
|
||||
}
|
||||
}
|
||||
|
||||
private final InheritableThreadLocal<Carrier<T>> value = new InheritableThreadLocal<>() {
|
||||
@Override
|
||||
protected Carrier<T> childValue(Carrier<T> parentValue) {
|
||||
return new Carrier<>(parentValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Carrier<T> initialValue() {
|
||||
return new Carrier<>();
|
||||
}
|
||||
};
|
||||
|
||||
public T get() {
|
||||
return value.get().getValue();
|
||||
}
|
||||
|
||||
public boolean isBound() {
|
||||
return value.get().isPresent();
|
||||
}
|
||||
|
||||
public T orElse(T other) {
|
||||
return value.get().orElse(other);
|
||||
}
|
||||
|
||||
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
|
||||
return value.get().orElseThrow(exceptionSupplier);
|
||||
}
|
||||
|
||||
private static class Carrier<T> {
|
||||
private Deque<T> value;
|
||||
private Carrier<T> parent;
|
||||
|
||||
public Carrier() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public Carrier(Carrier<T> parent) {
|
||||
this.value = new LinkedList<>();
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
if (!value.isEmpty()) return value.peek();
|
||||
if (parent == null) throw new NoSuchElementException("No value present");
|
||||
return parent.getValue();
|
||||
}
|
||||
|
||||
public boolean isPresent() {
|
||||
if (!value.isEmpty()) return true;
|
||||
if (parent == null) return false;
|
||||
return parent.isPresent();
|
||||
}
|
||||
|
||||
public void setValue(T value) {
|
||||
this.value.push(value);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
value.pop();
|
||||
}
|
||||
|
||||
public T orElse(T other) {
|
||||
if (!value.isEmpty()) return value.peek();
|
||||
if (parent == null) return other;
|
||||
return parent.orElse(other);
|
||||
}
|
||||
|
||||
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
|
||||
if (!value.isEmpty()) return value.peek();
|
||||
if (parent == null) throw exceptionSupplier.get();
|
||||
return parent.orElseThrow(exceptionSupplier);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package io.gitlab.jfronny.commons.concurrent;
|
||||
|
||||
public class StructureViolationException extends RuntimeException {
|
||||
public StructureViolationException() {
|
||||
}
|
||||
|
||||
public StructureViolationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue