obsidian-launcher/src/main/com/google/common/cache/CacheBuilder.java
2022-08-09 17:30:12 -07:00

388 lines
14 KiB
Java

package com.google.common.cache;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Ascii;
import com.google.common.base.Equivalence;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.base.Ticker;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.CheckReturnValue;
@GwtCompatible(
emulated = true
)
public final class CacheBuilder<K, V> {
private static final int DEFAULT_INITIAL_CAPACITY = 16;
private static final int DEFAULT_CONCURRENCY_LEVEL = 4;
private static final int DEFAULT_EXPIRATION_NANOS = 0;
private static final int DEFAULT_REFRESH_NANOS = 0;
static final Supplier<? extends AbstractCache.StatsCounter> NULL_STATS_COUNTER = Suppliers.ofInstance(new AbstractCache.StatsCounter() {
public void recordHits(int count) {
}
public void recordMisses(int count) {
}
public void recordLoadSuccess(long loadTime) {
}
public void recordLoadException(long loadTime) {
}
public void recordEviction() {
}
public CacheStats snapshot() {
return CacheBuilder.EMPTY_STATS;
}
});
static final CacheStats EMPTY_STATS = new CacheStats(0L, 0L, 0L, 0L, 0L, 0L);
static final Supplier<AbstractCache.StatsCounter> CACHE_STATS_COUNTER = new Supplier<AbstractCache.StatsCounter>() {
public AbstractCache.StatsCounter get() {
return new AbstractCache.SimpleStatsCounter();
}
};
static final Ticker NULL_TICKER = new Ticker() {
public long read() {
return 0L;
}
};
private static final Logger logger = Logger.getLogger(CacheBuilder.class.getName());
static final int UNSET_INT = -1;
boolean strictParsing = true;
int initialCapacity = -1;
int concurrencyLevel = -1;
long maximumSize = -1L;
long maximumWeight = -1L;
Weigher<? super K, ? super V> weigher;
LocalCache.Strength keyStrength;
LocalCache.Strength valueStrength;
long expireAfterWriteNanos = -1L;
long expireAfterAccessNanos = -1L;
long refreshNanos = -1L;
Equivalence<Object> keyEquivalence;
Equivalence<Object> valueEquivalence;
RemovalListener<? super K, ? super V> removalListener;
Ticker ticker;
Supplier<? extends AbstractCache.StatsCounter> statsCounterSupplier;
CacheBuilder() {
this.statsCounterSupplier = NULL_STATS_COUNTER;
}
public static CacheBuilder<Object, Object> newBuilder() {
return new CacheBuilder();
}
@Beta
@GwtIncompatible("To be supported")
public static CacheBuilder<Object, Object> from(CacheBuilderSpec spec) {
return spec.toCacheBuilder().lenientParsing();
}
@Beta
@GwtIncompatible("To be supported")
public static CacheBuilder<Object, Object> from(String spec) {
return from(CacheBuilderSpec.parse(spec));
}
@GwtIncompatible("To be supported")
CacheBuilder<K, V> lenientParsing() {
this.strictParsing = false;
return this;
}
@GwtIncompatible("To be supported")
CacheBuilder<K, V> keyEquivalence(Equivalence<Object> equivalence) {
Preconditions.checkState(this.keyEquivalence == null, "key equivalence was already set to %s", this.keyEquivalence);
this.keyEquivalence = (Equivalence)Preconditions.checkNotNull(equivalence);
return this;
}
Equivalence<Object> getKeyEquivalence() {
return (Equivalence)MoreObjects.firstNonNull(this.keyEquivalence, this.getKeyStrength().defaultEquivalence());
}
@GwtIncompatible("To be supported")
CacheBuilder<K, V> valueEquivalence(Equivalence<Object> equivalence) {
Preconditions.checkState(this.valueEquivalence == null, "value equivalence was already set to %s", this.valueEquivalence);
this.valueEquivalence = (Equivalence)Preconditions.checkNotNull(equivalence);
return this;
}
Equivalence<Object> getValueEquivalence() {
return (Equivalence)MoreObjects.firstNonNull(this.valueEquivalence, this.getValueStrength().defaultEquivalence());
}
public CacheBuilder<K, V> initialCapacity(int initialCapacity) {
Preconditions.checkState(this.initialCapacity == -1, "initial capacity was already set to %s", this.initialCapacity);
Preconditions.checkArgument(initialCapacity >= 0);
this.initialCapacity = initialCapacity;
return this;
}
int getInitialCapacity() {
return this.initialCapacity == -1 ? 16 : this.initialCapacity;
}
public CacheBuilder<K, V> concurrencyLevel(int concurrencyLevel) {
Preconditions.checkState(this.concurrencyLevel == -1, "concurrency level was already set to %s", this.concurrencyLevel);
Preconditions.checkArgument(concurrencyLevel > 0);
this.concurrencyLevel = concurrencyLevel;
return this;
}
int getConcurrencyLevel() {
return this.concurrencyLevel == -1 ? 4 : this.concurrencyLevel;
}
public CacheBuilder<K, V> maximumSize(long size) {
Preconditions.checkState(this.maximumSize == -1L, "maximum size was already set to %s", this.maximumSize);
Preconditions.checkState(this.maximumWeight == -1L, "maximum weight was already set to %s", this.maximumWeight);
Preconditions.checkState(this.weigher == null, "maximum size can not be combined with weigher");
Preconditions.checkArgument(size >= 0L, "maximum size must not be negative");
this.maximumSize = size;
return this;
}
@GwtIncompatible("To be supported")
public CacheBuilder<K, V> maximumWeight(long weight) {
Preconditions.checkState(this.maximumWeight == -1L, "maximum weight was already set to %s", this.maximumWeight);
Preconditions.checkState(this.maximumSize == -1L, "maximum size was already set to %s", this.maximumSize);
this.maximumWeight = weight;
Preconditions.checkArgument(weight >= 0L, "maximum weight must not be negative");
return this;
}
@GwtIncompatible("To be supported")
public <K1 extends K, V1 extends V> CacheBuilder<K1, V1> weigher(Weigher<? super K1, ? super V1> weigher) {
Preconditions.checkState(this.weigher == null);
if (this.strictParsing) {
Preconditions.checkState(this.maximumSize == -1L, "weigher can not be combined with maximum size", this.maximumSize);
}
this.weigher = (Weigher)Preconditions.checkNotNull(weigher);
return this;
}
long getMaximumWeight() {
if (this.expireAfterWriteNanos != 0L && this.expireAfterAccessNanos != 0L) {
return this.weigher == null ? this.maximumSize : this.maximumWeight;
} else {
return 0L;
}
}
<K1 extends K, V1 extends V> Weigher<K1, V1> getWeigher() {
return (Weigher)MoreObjects.firstNonNull(this.weigher, CacheBuilder.OneWeigher.INSTANCE);
}
@GwtIncompatible("java.lang.ref.WeakReference")
public CacheBuilder<K, V> weakKeys() {
return this.setKeyStrength(LocalCache.Strength.WEAK);
}
CacheBuilder<K, V> setKeyStrength(LocalCache.Strength strength) {
Preconditions.checkState(this.keyStrength == null, "Key strength was already set to %s", this.keyStrength);
this.keyStrength = (LocalCache.Strength)Preconditions.checkNotNull(strength);
return this;
}
LocalCache.Strength getKeyStrength() {
return (LocalCache.Strength)MoreObjects.firstNonNull(this.keyStrength, LocalCache.Strength.STRONG);
}
@GwtIncompatible("java.lang.ref.WeakReference")
public CacheBuilder<K, V> weakValues() {
return this.setValueStrength(LocalCache.Strength.WEAK);
}
@GwtIncompatible("java.lang.ref.SoftReference")
public CacheBuilder<K, V> softValues() {
return this.setValueStrength(LocalCache.Strength.SOFT);
}
CacheBuilder<K, V> setValueStrength(LocalCache.Strength strength) {
Preconditions.checkState(this.valueStrength == null, "Value strength was already set to %s", this.valueStrength);
this.valueStrength = (LocalCache.Strength)Preconditions.checkNotNull(strength);
return this;
}
LocalCache.Strength getValueStrength() {
return (LocalCache.Strength)MoreObjects.firstNonNull(this.valueStrength, LocalCache.Strength.STRONG);
}
public CacheBuilder<K, V> expireAfterWrite(long duration, TimeUnit unit) {
Preconditions.checkState(this.expireAfterWriteNanos == -1L, "expireAfterWrite was already set to %s ns", this.expireAfterWriteNanos);
Preconditions.checkArgument(duration >= 0L, "duration cannot be negative: %s %s", duration, unit);
this.expireAfterWriteNanos = unit.toNanos(duration);
return this;
}
long getExpireAfterWriteNanos() {
return this.expireAfterWriteNanos == -1L ? 0L : this.expireAfterWriteNanos;
}
public CacheBuilder<K, V> expireAfterAccess(long duration, TimeUnit unit) {
Preconditions.checkState(this.expireAfterAccessNanos == -1L, "expireAfterAccess was already set to %s ns", this.expireAfterAccessNanos);
Preconditions.checkArgument(duration >= 0L, "duration cannot be negative: %s %s", duration, unit);
this.expireAfterAccessNanos = unit.toNanos(duration);
return this;
}
long getExpireAfterAccessNanos() {
return this.expireAfterAccessNanos == -1L ? 0L : this.expireAfterAccessNanos;
}
@Beta
@GwtIncompatible("To be supported (synchronously).")
public CacheBuilder<K, V> refreshAfterWrite(long duration, TimeUnit unit) {
Preconditions.checkNotNull(unit);
Preconditions.checkState(this.refreshNanos == -1L, "refresh was already set to %s ns", this.refreshNanos);
Preconditions.checkArgument(duration > 0L, "duration must be positive: %s %s", duration, unit);
this.refreshNanos = unit.toNanos(duration);
return this;
}
long getRefreshNanos() {
return this.refreshNanos == -1L ? 0L : this.refreshNanos;
}
public CacheBuilder<K, V> ticker(Ticker ticker) {
Preconditions.checkState(this.ticker == null);
this.ticker = (Ticker)Preconditions.checkNotNull(ticker);
return this;
}
Ticker getTicker(boolean recordsTime) {
if (this.ticker != null) {
return this.ticker;
} else {
return recordsTime ? Ticker.systemTicker() : NULL_TICKER;
}
}
@CheckReturnValue
public <K1 extends K, V1 extends V> CacheBuilder<K1, V1> removalListener(RemovalListener<? super K1, ? super V1> listener) {
Preconditions.checkState(this.removalListener == null);
this.removalListener = (RemovalListener)Preconditions.checkNotNull(listener);
return this;
}
<K1 extends K, V1 extends V> RemovalListener<K1, V1> getRemovalListener() {
return (RemovalListener)MoreObjects.firstNonNull(this.removalListener, CacheBuilder.NullListener.INSTANCE);
}
public CacheBuilder<K, V> recordStats() {
this.statsCounterSupplier = CACHE_STATS_COUNTER;
return this;
}
boolean isRecordingStats() {
return this.statsCounterSupplier == CACHE_STATS_COUNTER;
}
Supplier<? extends AbstractCache.StatsCounter> getStatsCounterSupplier() {
return this.statsCounterSupplier;
}
public <K1 extends K, V1 extends V> LoadingCache<K1, V1> build(CacheLoader<? super K1, V1> loader) {
this.checkWeightWithWeigher();
return new LocalCache.LocalLoadingCache(this, loader);
}
public <K1 extends K, V1 extends V> Cache<K1, V1> build() {
this.checkWeightWithWeigher();
this.checkNonLoadingCache();
return new LocalCache.LocalManualCache(this);
}
private void checkNonLoadingCache() {
Preconditions.checkState(this.refreshNanos == -1L, "refreshAfterWrite requires a LoadingCache");
}
private void checkWeightWithWeigher() {
if (this.weigher == null) {
Preconditions.checkState(this.maximumWeight == -1L, "maximumWeight requires weigher");
} else if (this.strictParsing) {
Preconditions.checkState(this.maximumWeight != -1L, "weigher requires maximumWeight");
} else if (this.maximumWeight == -1L) {
logger.log(Level.WARNING, "ignoring weigher specified without maximumWeight");
}
}
public String toString() {
MoreObjects.ToStringHelper s = MoreObjects.toStringHelper((Object)this);
if (this.initialCapacity != -1) {
s.add("initialCapacity", this.initialCapacity);
}
if (this.concurrencyLevel != -1) {
s.add("concurrencyLevel", this.concurrencyLevel);
}
if (this.maximumSize != -1L) {
s.add("maximumSize", this.maximumSize);
}
if (this.maximumWeight != -1L) {
s.add("maximumWeight", this.maximumWeight);
}
long var2;
if (this.expireAfterWriteNanos != -1L) {
var2 = this.expireAfterWriteNanos;
s.add("expireAfterWrite", (new StringBuilder(22)).append(var2).append("ns").toString());
}
if (this.expireAfterAccessNanos != -1L) {
var2 = this.expireAfterAccessNanos;
s.add("expireAfterAccess", (new StringBuilder(22)).append(var2).append("ns").toString());
}
if (this.keyStrength != null) {
s.add("keyStrength", Ascii.toLowerCase(this.keyStrength.toString()));
}
if (this.valueStrength != null) {
s.add("valueStrength", Ascii.toLowerCase(this.valueStrength.toString()));
}
if (this.keyEquivalence != null) {
s.addValue("keyEquivalence");
}
if (this.valueEquivalence != null) {
s.addValue("valueEquivalence");
}
if (this.removalListener != null) {
s.addValue("removalListener");
}
return s.toString();
}
static enum OneWeigher implements Weigher<Object, Object> {
INSTANCE;
public int weigh(Object key, Object value) {
return 1;
}
}
static enum NullListener implements RemovalListener<Object, Object> {
INSTANCE;
public void onRemoval(RemovalNotification<Object, Object> notification) {
}
}
}