All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.rx.cache.WeakCache Maven / Gradle / Ivy

package org.rx.cache;

import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

import org.rx.App;
import org.rx.Logger;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;

import static org.rx.Contract.as;
import static org.rx.Contract.require;

/**
 * http://blog.csdn.net/nicolasyan/article/details/50840852
 */
public class WeakCache {
    private static WeakCache instance;

    public static WeakCache getInstance() {
        if (instance == null) {
            synchronized (WeakCache.class) {
                if (instance == null) {
                    instance = new WeakCache<>();
                }
            }
        }
        return instance;
    }

    public static Object getOrStore(Class caller, String key, Function supplier) {
        require(caller, key, supplier);

        String k = App.cacheKey(caller.getName() + key);
        return getInstance().getOrAdd(k, p -> supplier.apply(key));
    }

    private ConcurrentMap container;
    private boolean                      softRef;

    public boolean isSoftRef() {
        return softRef;
    }

    public void setSoftRef(boolean softRef) {
        this.softRef = softRef;
    }

    public WeakCache() {
        container = new ConcurrentHashMap<>();
    }

    private Reference getItem(TK key) {
        require(key);

        return container.get(key);
    }

    public void add(TK key, TV val) {
        add(key, val, softRef);
    }

    public void add(TK key, TV val, boolean isSoftRef) {
        require(key, val);

        Reference ref = getItem(key);
        if (ref != null && isSoftRef ? ref instanceof SoftReference : ref instanceof WeakReference) {
            Object v = ref.get();
            if (v != null && v.equals(val)) {
                return;
            }
        }
        container.put(key, isSoftRef ? new SoftReference(val) : new WeakReference(val));
    }

    public void remove(TK key) {
        remove(key, true);
    }

    public void remove(TK key, boolean destroy) {
        require(key);

        Reference ref = container.remove(key);
        if (ref == null) {
            return;
        }
        AutoCloseable ac;
        if (destroy && (ac = as(ref.get(), AutoCloseable.class)) != null) {
            try {
                ac.close();
            } catch (Exception ex) {
                Logger.error(ex, "Auto close error");
            }
        }
        ref.clear();
    }

    public TV get(TK key) {
        Reference ref = getItem(key);
        if (ref == null) {
            return null;
        }
        return (TV) ref.get();
    }

    public TV getOrAdd(TK key, Function supplier) {
        return getOrAdd(key, supplier, softRef);
    }

    public TV getOrAdd(TK key, Function supplier, boolean isSoftRef) {
        require(supplier);

        TV v;
        Reference ref = getItem(key);
        if (ref == null || (v = (TV) ref.get()) == null) {
            add(key, v = supplier.apply(key), isSoftRef);
        }
        return v;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy