diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/internal/model/ValueCache.java b/com.amd.aparapi/src/java/com/amd/aparapi/internal/model/ValueCache.java new file mode 100644 index 0000000000000000000000000000000000000000..ef66a53fdeca66f8da816f12f1d88e360d749303 --- /dev/null +++ b/com.amd.aparapi/src/java/com/amd/aparapi/internal/model/ValueCache.java @@ -0,0 +1,46 @@ +package com.amd.aparapi.internal.model; + +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +//import java.util.function.Supplier; + +public final class ValueCache<K, V, T extends Throwable> { + // @FunctionalInterface + public interface ThrowingValueComputer<K, V, T extends Throwable> { + V compute(K key) throws T; + } + + // @FunctionalInterface + public interface ValueComputer<K, V> extends ThrowingValueComputer<K, V, RuntimeException>{ + // Marker interface + } + + public static <K, V, T extends Throwable> ValueCache<K, V, T> on(ThrowingValueComputer<K, V, T> computer) { + return new ValueCache<K, V, T>(computer); + } + + private final ConcurrentMap<K, SoftReference<V>> map = new ConcurrentHashMap<>(); + + private final ThrowingValueComputer<K, V, T> computer; + + private ValueCache(ThrowingValueComputer<K, V, T> computer) { + this.computer = computer; + } + + public V computeIfAbsent(K key) throws T { + Reference<V> reference = map.get(key); + V value = reference == null ? null : reference.get(); + if (value == null) { + value = computer.compute(key); + map.put(key, new SoftReference<>(value)); + } + return value; + } + + public void invalidate() { + map.clear(); + } +}