Ver Fonte

LazyRef

Ranides Atterwim há 12 anos atrás
pai
commit
bdd9c600f5
1 ficheiros alterados com 137 adições e 0 exclusões
  1. 137 0
      src/main/java/net/ranides/assira/generic/LazyRef.java

+ 137 - 0
src/main/java/net/ranides/assira/generic/LazyRef.java

@@ -0,0 +1,137 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/everything
+ */
+
+package net.ranides.assira.generic;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicReference;
+import net.ranides.assira.reflection.MethodPointer;
+
+/**
+ *
+ * @author Mariusz Sieron <m.sieron@samsung.com>
+ * @param <T>
+ */
+public abstract class LazyRef<T> {
+
+    protected final Callable<T> generator;
+
+    protected LazyRef(Callable<T> generator) {
+        this.generator = generator;
+    }
+
+    public abstract T get();
+
+    public static <T> LazyRef<T> nonlocking(Callable<T> generator) {
+        return new NonLocking<T>(generator);
+    }
+
+    public static <T> LazyRef<T> nonlocking(MethodPointer<T> method) {
+        return nonlocking(LazyRef.wrap(method));
+    }
+
+    public static <T> LazyRef<T> locking(Callable<T> generator) {
+        return new Locking<T>(generator);
+    }
+
+    public static <T> LazyRef<T> locking(MethodPointer<T> method) {
+        return locking(LazyRef.wrap(method));
+    }
+
+    public static <T> LazyRef<T> lockfree(Callable<T> generator) {
+        return new LockFree<T>(generator);
+    }
+
+    public static <T> LazyRef<T> lockfree(MethodPointer<T> method) {
+        return lockfree(LazyRef.wrap(method));
+    }
+
+    private static <T> Callable<T> wrap(final MethodPointer<T> method) {
+        return new Callable<T>() {
+            public T call() throws Exception {
+                return method.call();
+            }
+        };
+    }
+
+    private static class NonLocking<T> extends LazyRef<T> {
+
+        private T ret;
+
+        public NonLocking(Callable<T> generator) {
+            super(generator);
+        }
+
+        @Override
+        public T get() {
+            try {
+                if( ret == null) {
+                    ret = generator.call();
+                }
+                return ret;
+            } catch(Exception cause) {
+                throw new RuntimeException(cause);
+            }
+        }
+
+    }
+
+    private static class Locking<T> extends LazyRef<T> {
+
+        private volatile T ref = null;
+
+        public Locking(Callable<T> generator) {
+            super(generator);
+        }
+
+        public T get() {
+            try {
+                T temp = ref;
+                if(null == temp) {
+                    synchronized(this) {
+                        if(null == ref) {
+                            ref = temp = generator.call();
+                        }
+                    }
+                }
+                return temp;
+            } catch(Exception cause) {
+                throw new RuntimeException(cause);
+            }
+        }
+
+    }
+
+    private static class LockFree<T> extends LazyRef<T> {
+
+        private static enum State { UNDEFINED_1, UNDEFINED_2 }
+
+        private final AtomicReference<Object> ref = new AtomicReference<Object>(State.UNDEFINED_1);
+
+        public LockFree(Callable<T> generator) {
+            super(generator);
+        }
+
+        public T get() {
+            try {
+                if( ref.compareAndSet(State.UNDEFINED_1, State.UNDEFINED_2) ) {
+                    ref.set( generator.call() );
+                    return (T)ref.get();
+                }
+                if( ref.compareAndSet(State.UNDEFINED_2, State.UNDEFINED_1) ) {
+                    ref.set( generator.call() );
+                    return (T)ref.get();
+                }
+                return (T)ref.get();
+            } catch(Exception cause) {
+                throw new RuntimeException(cause);
+            }
+        }
+
+    }
+
+}