summaryrefslogtreecommitdiffstats
path: root/yolean
diff options
context:
space:
mode:
authorJon Marius Venstad <jonmv@users.noreply.github.com>2022-05-02 21:08:17 +0200
committerGitHub <noreply@github.com>2022-05-02 21:08:17 +0200
commit6058f5f8d2ed19ca3c0461e7080680a093834823 (patch)
tree3e09032c623789406abfa2d42ea74b7064cb7087 /yolean
parent04898b34190a3e3bb9d3053e11eb892bc48ff842 (diff)
Revert "Jonmv/remove last controller jersey client [run-systemtest]"
Diffstat (limited to 'yolean')
-rw-r--r--yolean/abi-spec.json30
-rw-r--r--yolean/src/main/java/com/yahoo/yolean/concurrent/Memoized.java64
-rw-r--r--yolean/src/test/java/com/yahoo/yolean/concurrent/MemoizedTest.java101
3 files changed, 0 insertions, 195 deletions
diff --git a/yolean/abi-spec.json b/yolean/abi-spec.json
index 553a8aa61e1..6285cc54118 100644
--- a/yolean/abi-spec.json
+++ b/yolean/abi-spec.json
@@ -234,36 +234,6 @@
],
"fields": []
},
- "com.yahoo.yolean.concurrent.Memoized$Closer": {
- "superClass": "java.lang.Object",
- "interfaces": [],
- "attributes": [
- "public",
- "interface",
- "abstract"
- ],
- "methods": [
- "public abstract void close(java.lang.Object)"
- ],
- "fields": []
- },
- "com.yahoo.yolean.concurrent.Memoized": {
- "superClass": "java.lang.Object",
- "interfaces": [
- "java.util.function.Supplier",
- "java.lang.AutoCloseable"
- ],
- "attributes": [
- "public"
- ],
- "methods": [
- "public void <init>(java.util.function.Supplier, com.yahoo.yolean.concurrent.Memoized$Closer)",
- "public static com.yahoo.yolean.concurrent.Memoized of(java.util.function.Supplier)",
- "public java.lang.Object get()",
- "public void close()"
- ],
- "fields": []
- },
"com.yahoo.yolean.concurrent.ResourceFactory": {
"superClass": "java.lang.Object",
"interfaces": [],
diff --git a/yolean/src/main/java/com/yahoo/yolean/concurrent/Memoized.java b/yolean/src/main/java/com/yahoo/yolean/concurrent/Memoized.java
deleted file mode 100644
index e8660504a8a..00000000000
--- a/yolean/src/main/java/com/yahoo/yolean/concurrent/Memoized.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.yahoo.yolean.concurrent;
-
-import java.util.function.Supplier;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * Wraps a lazily initialised resource which needs to be shut down.
- * The wrapped supplier may not return {@code null}, and should be retryable on failure.
- * If it throws, it will be retried if {@link #get} is retried. A supplier that fails to
- * clean up partial state on failure may cause a resource leak.
- *
- * @author jonmv
- */
-public class Memoized<T, E extends Exception> implements Supplier<T>, AutoCloseable {
-
- /** Provides a tighter bound on the thrown exception type. */
- @FunctionalInterface
- 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;
- private volatile T wrapped;
- private Supplier<T> factory;
-
- public Memoized(Supplier<T> factory, Closer<T, E> closer) {
- this.factory = requireNonNull(factory);
- this.closer = requireNonNull(closer);
- }
-
- public static <T extends AutoCloseable> Memoized<T, ?> of(Supplier<T> factory) {
- return new Memoized<>(factory, AutoCloseable::close);
- }
-
- @Override
- public T get() {
- // Double-checked locking: try the variable, and if not initialized, try to initialize it.
- if (wrapped == null) synchronized (monitor) {
- // Ensure the factory is called only once, by clearing it once successfully called.
- if (factory != null) wrapped = requireNonNull(factory.get());
- factory = null;
-
- // If we found the factory, we won the initialization race, and return normally; otherwise
- // if wrapped is non-null, we lost the race, wrapped was set by the winner, and we return; otherwise
- // we tried to initialise because wrapped was cleared by closing this, and we fail.
- if (wrapped == null) throw new IllegalStateException("already closed");
- }
- return wrapped;
- }
-
- @Override
- public void close() throws E {
- // Alter state only when synchronized with calls to get().
- synchronized (monitor) {
- // Ensure we only try to close the generated resource once, by clearing it after picking it up here.
- T maybe = wrapped;
- wrapped = null;
- // Clear the factory, to signal this has been closed.
- factory = null;
- if (maybe != null) closer.close(maybe);
- }
- }
-
-} \ No newline at end of file
diff --git a/yolean/src/test/java/com/yahoo/yolean/concurrent/MemoizedTest.java b/yolean/src/test/java/com/yahoo/yolean/concurrent/MemoizedTest.java
deleted file mode 100644
index 7f2f49c75f2..00000000000
--- a/yolean/src/test/java/com/yahoo/yolean/concurrent/MemoizedTest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package com.yahoo.yolean.concurrent;
-
-import org.junit.Test;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.Phaser;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Supplier;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.fail;
-
-/**
- * @author jonmv
- */
-public class MemoizedTest {
-
- final Phaser phaser = new Phaser();
- final int threads = 128;
-
- @Test
- public void test() throws ExecutionException, InterruptedException {
- var lazy = new Memoized<>(new OnceSupplier(), OnceCloseable::close);
- phaser.register(); // test thread
- phaser.register(); // whoever calls the factory
-
- Phaser latch = new Phaser(threads + 1);
- ExecutorService executor = Executors.newFixedThreadPool(threads);
- List<Future<?>> futures = new ArrayList<>();
- for (int i = 0; i < 128; i++) {
- futures.add(executor.submit(() -> {
- latch.arriveAndAwaitAdvance();
- lazy.get().rendezvous();
- while (true) lazy.get();
- }));
- }
-
- // All threads waiting for latch, will race to factory
- latch.arriveAndAwaitAdvance();
-
- // One thread waiting in factory, the others are blocked, will go to rendezvous
- phaser.arriveAndAwaitAdvance();
-
- // All threads waiting in rendezvous, will repeatedly get until failure
- phaser.arriveAndAwaitAdvance();
-
- // Unsynchronized close should be detected by all threads
- lazy.close();
-
- // Close should carry through only once
- lazy.close();
-
- assertEquals("already closed",
- assertThrows(IllegalStateException.class, lazy::get).getMessage());
-
- for (Future<?> future : futures)
- assertEquals("java.lang.IllegalStateException: already closed",
- assertThrows(ExecutionException.class, future::get).getMessage());
-
- executor.shutdown();
- }
-
- @Test
- public void closeBeforeFirstGet() throws Exception {
- OnceSupplier supplier = new OnceSupplier();
- Memoized<OnceCloseable, ?> lazy = Memoized.of(supplier);
- lazy.close();
- assertEquals("already closed",
- assertThrows(IllegalStateException.class, lazy::get).getMessage());
- lazy.close();
- assertFalse(supplier.initialized.get());
- }
-
- class OnceSupplier implements Supplier<OnceCloseable> {
- final AtomicBoolean initialized = new AtomicBoolean();
- @Override public OnceCloseable get() {
- phaser.arriveAndAwaitAdvance();
- if ( ! initialized.compareAndSet(false, true)) fail("initialized more than once");
- phaser.bulkRegister(threads - 1); // register all the threads who didn't get the factory
- return new OnceCloseable();
- }
- }
-
- class OnceCloseable implements AutoCloseable {
- final AtomicBoolean closed = new AtomicBoolean();
- @Override public void close() {
- if ( ! closed.compareAndSet(false, true)) fail("closed more than once");
- }
- void rendezvous() {
- phaser.arriveAndAwaitAdvance();
- }
- }
-
-}