CacheBack.java
package space.sunqian.common.cache;
import space.sunqian.annotations.Nonnull;
import space.sunqian.annotations.Nullable;
import space.sunqian.common.Fs;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.Map;
final class CacheBack {
static <K, V> @Nonnull SimpleCache<K, V> ofWeak() {
return new WeakCache<>();
}
static <K, V> @Nonnull SimpleCache<K, V> ofSoft() {
return new SoftCache<>();
}
static <K, V> @Nonnull SimpleCache<K, V> ofPhantom() {
return new PhantomCache<>();
}
static <K, V> @Nonnull SimpleCache<K, V> ofStrong() {
return new StrongCache<>();
}
private static <K, V> void compareAndRemove(@Nonnull Map<K, V> map, K key, V value) {
V v = map.get(key);
if (v == value) {
map.remove(key);
}
// map.computeIfPresent(key, (k, old) -> {
// if (old == value) {
// return null;
// }
// return old;
// });
}
private static abstract class ReferenceCache<K, V> extends AbstractSimpleCache<K, V> {
protected final @Nonnull ReferenceQueue<Object> queue = new ReferenceQueue<>();
@Override
public void clean() {
while (true) {
@Nullable Reference<?> reference = queue.poll();
if (reference == null) {
return;
}
Value<K> rv = Fs.as(reference);
compareAndRemove(cacheMap, rv.key(), rv);
}
}
}
private static final class WeakCache<K, V> extends ReferenceCache<K, V> {
@Override
protected @Nonnull Value<K> generate(@Nonnull K key, @Nonnull Object value) {
return new WeakValue(key, value);
}
private final class WeakValue extends WeakReference<Object> implements Value<K> {
private final @Nonnull K key;
WeakValue(@Nonnull K key, @Nonnull Object value) {
super(value, queue);
this.key = key;
}
@Override
public @Nonnull K key() {
return key;
}
@Override
public @Nullable Object refValue() {
return get();
}
@Override
public void invalid() {
enqueue();
}
}
}
private static final class SoftCache<K, V> extends ReferenceCache<K, V> {
@Override
protected @Nonnull Value<K> generate(@Nonnull K key, @Nonnull Object value) {
return new SoftValue(key, value);
}
private final class SoftValue extends SoftReference<Object> implements Value<K> {
private final @Nonnull K key;
SoftValue(@Nonnull K key, @Nonnull Object value) {
super(value, queue);
this.key = key;
}
@Override
public @Nonnull K key() {
return key;
}
@Override
public @Nullable Object refValue() {
return get();
}
@Override
public void invalid() {
enqueue();
}
}
}
private static final class PhantomCache<K, V> extends ReferenceCache<K, V> {
@Override
protected @Nonnull Value<K> generate(@Nonnull K key, @Nonnull Object value) {
return new PhantomValue(key, value);
}
private final class PhantomValue extends PhantomReference<Object> implements Value<K> {
private final @Nonnull K key;
PhantomValue(@Nonnull K key, @Nonnull Object value) {
super(value, queue);
this.key = key;
}
@Override
public @Nonnull K key() {
return key;
}
@Override
public @Nullable Object refValue() {
return get();
}
@Override
public void invalid() {
enqueue();
}
}
}
private static final class StrongCache<K, V> extends AbstractSimpleCache<K, V> {
@Override
public void clean() {
}
@Override
protected @Nonnull Value<K> generate(@Nonnull K key, @Nonnull Object value) {
return new StrongValue(key, value);
}
private final class StrongValue implements Value<K> {
private final @Nonnull K key;
private @Nullable Object value;
StrongValue(@Nonnull K key, @Nonnull Object value) {
this.key = key;
this.value = value;
}
@Override
public @Nonnull K key() {
return key;
}
@Override
public @Nullable Object refValue() {
return value;
}
@Override
public void invalid() {
value = null;
compareAndRemove(cacheMap, key(), StrongValue.this);
}
}
}
private CacheBack() {
}
}