aboutsummaryrefslogtreecommitdiffstats
path: root/yolean
diff options
context:
space:
mode:
authorjonmv <venstad@gmail.com>2022-05-03 12:39:11 +0200
committerjonmv <venstad@gmail.com>2022-05-03 12:39:11 +0200
commit04ccad38765b7e872be657dcbb10037f6ad172d0 (patch)
tree8d4d0d07cb66b707396391556c34cc887c9f2277 /yolean
parentca4cd3fdaf0aacfa3ad22778c411857c390b4fc3 (diff)
Allow combining memoized objects
Diffstat (limited to 'yolean')
-rw-r--r--yolean/src/main/java/com/yahoo/yolean/concurrent/Memoized.java40
1 files changed, 38 insertions, 2 deletions
diff --git a/yolean/src/main/java/com/yahoo/yolean/concurrent/Memoized.java b/yolean/src/main/java/com/yahoo/yolean/concurrent/Memoized.java
index e8660504a8a..6bd9bd5add3 100644
--- a/yolean/src/main/java/com/yahoo/yolean/concurrent/Memoized.java
+++ b/yolean/src/main/java/com/yahoo/yolean/concurrent/Memoized.java
@@ -1,5 +1,6 @@
package com.yahoo.yolean.concurrent;
+import java.util.function.Function;
import java.util.function.Supplier;
import static java.util.Objects.requireNonNull;
@@ -14,9 +15,16 @@ import static java.util.Objects.requireNonNull;
*/
public class Memoized<T, E extends Exception> implements Supplier<T>, AutoCloseable {
- /** Provides a tighter bound on the thrown exception type. */
+ /**
+ * Provides a tighter bound on the thrown exception type.
+ */
@FunctionalInterface
- public interface Closer<T, E extends Exception> { void close(T t) throws E; }
+ public interface Closer<T, E extends Exception> {
+
+ void close(T t) throws E;
+
+ }
+
private final Object monitor = new Object();
private final Closer<T, E> closer;
@@ -32,6 +40,10 @@ public class Memoized<T, E extends Exception> implements Supplier<T>, AutoClosea
return new Memoized<>(factory, AutoCloseable::close);
}
+ public static <T, U, E extends Exception, F extends E, G extends E> Memoized<U, E> combine(Memoized<T, F> inner, Function<T, U> outer, Closer<U, G> closer) {
+ return new Memoized<>(() -> outer.apply(inner.get()), compose(closer, inner::close));
+ }
+
@Override
public T get() {
// Double-checked locking: try the variable, and if not initialized, try to initialize it.
@@ -61,4 +73,28 @@ public class Memoized<T, E extends Exception> implements Supplier<T>, AutoClosea
}
}
+ private interface Thrower<E extends Exception> { void call() throws E; }
+
+ private static <T, E extends Exception, F extends E, G extends E> Closer<T, E> compose(Closer<T, G> inner, Thrower<F> outer) {
+ return parent -> {
+ Exception thrown = null;
+ try {
+ inner.close(parent);
+ }
+ catch (Exception e) {
+ thrown = e;
+ }
+ try {
+ outer.call();
+ }
+ catch (Exception e) {
+ if (thrown != null) thrown.addSuppressed(e);
+ else thrown = e;
+ }
+ @SuppressWarnings("unchecked")
+ E e = (E) thrown;
+ if (e != null) throw e;
+ };
+ }
+
} \ No newline at end of file