diff options
author | jonmv <venstad@gmail.com> | 2022-05-03 12:39:11 +0200 |
---|---|---|
committer | jonmv <venstad@gmail.com> | 2022-05-03 12:39:11 +0200 |
commit | 04ccad38765b7e872be657dcbb10037f6ad172d0 (patch) | |
tree | 8d4d0d07cb66b707396391556c34cc887c9f2277 /yolean | |
parent | ca4cd3fdaf0aacfa3ad22778c411857c390b4fc3 (diff) |
Allow combining memoized objects
Diffstat (limited to 'yolean')
-rw-r--r-- | yolean/src/main/java/com/yahoo/yolean/concurrent/Memoized.java | 40 |
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 |