![JAR search and dependency download from the Maven repository](/logo.png)
net.java.truevfs.ext.pacemaker.LruCache Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of truevfs-ext-pacemaker Show documentation
Show all versions of truevfs-ext-pacemaker Show documentation
Constrains the number of concurrently mounted archive file systems in
order to save some heap space.
This module provides a JMX interface for monitoring and management.
Add the JAR artifact of this module to the run time class path to
make its services available for service location in the client API
modules.
The newest version!
/*
* Copyright © 2005 - 2021 Schlichtherle IT Services.
* All rights reserved. Use is subject to license terms.
*/
package net.java.truevfs.ext.pacemaker;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Predicate;
import java.util.function.Supplier;
import static net.java.truecommons.shed.HashMaps.initialCapacity;
/**
* A simple cache set with a least-recently-used (LRU) eviction strategy.
* Note that unlike other caches whenever an item gets evicted, it gets added to a concurrent set which can get queried
* using the {@link #evicted} method for further processing, e.g. to close resources.
* This class is thread-safe.
*
* @param the type of the items
* @author Christian Schlichtherle
*/
final class LruCache {
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock();
private final ConcurrentMap evicted = new ConcurrentHashMap<>();
private final CacheMap cached = new CacheMap();
private volatile int maximumSize;
LruCache(final int initialMaximumSize) {
this.maximumSize = initialMaximumSize;
}
Set getEvictedView() { return evicted.keySet(); }
int getMaximumSize() { return maximumSize; }
void setMaximumSize(final int maximumSize) {
if (0 > maximumSize) {
throw new IllegalArgumentException();
}
this.maximumSize = maximumSize;
}
void add(T item) {
writeLocked(() -> cached.put(item, true));
}
void remove(T item) {
writeLocked(() -> cached.remove(item));
}
/**
* Records access to the given mount point.
* This method has no effect if the given mount point is not present in this LRU cache.
*/
void recordAccess(T item) {
// The lookup needs to be write-locked because the access-ordered cache map may get structurally modified as a
// side effect:
writeLocked(() -> cached.get(item));
}
boolean exists(Predicate predicate) {
return readLocked(() -> cached.exists(predicate));
}
private U readLocked(Supplier expr) {
return locked(readLock, expr);
}
private U writeLocked(Supplier expr) {
return locked(writeLock, expr);
}
private static U locked(final Lock lock, final Supplier expr) {
lock.lock();
try {
return expr.get();
} finally {
lock.unlock();
}
}
private final class CacheMap extends LinkedHashMap {
private static final long serialVersionUID = 0;
CacheMap() {
super(initialCapacity(maximumSize), 0.75f, true);
}
@Override
protected boolean removeEldestEntry(final Map.Entry eldest) {
if (size() > maximumSize) {
evicted.put(eldest.getKey(), eldest.getValue());
return true;
} else {
return false;
}
}
@Override
public Boolean put(final T key, final Boolean value) {
evicted.remove(key);
return super.put(key, value);
}
@Override
public Boolean remove(final Object key) {
evicted.remove(key);
return super.remove(key);
}
boolean exists(Predicate predicate) {
return keySet().stream().anyMatch(predicate);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy