mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2025-01-01 14:07:56 +01:00
Remove MRUCache
Now we're using ConcurrentHashMap, it's usefulness in terms of performance is debatable
This commit is contained in:
parent
adbd2fc81f
commit
4514a17eaf
@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of LuckPerms, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* Copyright (c) contributors
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package me.lucko.luckperms.common.cache;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of a most-recently-used cache with a mod counter, to prevent race conditions
|
|
||||||
* occurring when the cache is cleared whilst a calculation is taking place.
|
|
||||||
*
|
|
||||||
* @param <T> the cached type
|
|
||||||
*/
|
|
||||||
public abstract class MRUCache<T> {
|
|
||||||
private volatile T recent;
|
|
||||||
private final AtomicInteger modCount = new AtomicInteger();
|
|
||||||
|
|
||||||
protected int modCount() {
|
|
||||||
return this.modCount.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected T getRecent() {
|
|
||||||
return this.recent;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void offerRecent(int validAt, T offer) {
|
|
||||||
synchronized (this) {
|
|
||||||
if (validAt == this.modCount.get()) {
|
|
||||||
this.recent = offer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calling clearRecent effectively resets the instance. any other threads going to call
|
|
||||||
* offerRecent in the future with the previous mod count will be ignored.
|
|
||||||
*/
|
|
||||||
protected void clearRecent() {
|
|
||||||
synchronized (this) {
|
|
||||||
this.recent = null;
|
|
||||||
this.modCount.incrementAndGet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,7 +26,6 @@
|
|||||||
package me.lucko.luckperms.common.cacheddata;
|
package me.lucko.luckperms.common.cacheddata;
|
||||||
|
|
||||||
import me.lucko.luckperms.common.cache.LoadingMap;
|
import me.lucko.luckperms.common.cache.LoadingMap;
|
||||||
import me.lucko.luckperms.common.cache.MRUCache;
|
|
||||||
import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator;
|
import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator;
|
||||||
import me.lucko.luckperms.common.cacheddata.type.MetaCache;
|
import me.lucko.luckperms.common.cacheddata.type.MetaCache;
|
||||||
import me.lucko.luckperms.common.cacheddata.type.PermissionCache;
|
import me.lucko.luckperms.common.cacheddata.type.PermissionCache;
|
||||||
@ -183,7 +182,7 @@ public abstract class AbstractCachedDataManager implements CachedDataManager {
|
|||||||
this.meta.cleanup();
|
this.meta.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class AbstractContainer<C extends I, I extends CachedData> extends MRUCache<RecentData<C>> implements Container<I> {
|
private static final class AbstractContainer<C extends I, I extends CachedData> implements Container<I> {
|
||||||
private final Function<QueryOptions, C> cacheLoader;
|
private final Function<QueryOptions, C> cacheLoader;
|
||||||
private final LoadingMap<QueryOptions, C> cache;
|
private final LoadingMap<QueryOptions, C> cache;
|
||||||
|
|
||||||
@ -200,16 +199,8 @@ public abstract class AbstractCachedDataManager implements CachedDataManager {
|
|||||||
public @NonNull C get(@NonNull QueryOptions queryOptions) {
|
public @NonNull C get(@NonNull QueryOptions queryOptions) {
|
||||||
Objects.requireNonNull(queryOptions, "queryOptions");
|
Objects.requireNonNull(queryOptions, "queryOptions");
|
||||||
|
|
||||||
RecentData<C> recent = getRecent();
|
|
||||||
if (recent != null && queryOptions.equals(recent.queryOptions)) {
|
|
||||||
((UsageTracked) recent.data).recordUsage();
|
|
||||||
return recent.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
int modCount = modCount();
|
|
||||||
C data = this.cache.get(queryOptions);
|
C data = this.cache.get(queryOptions);
|
||||||
((UsageTracked) data).recordUsage();
|
((UsageTracked) data).recordUsage();
|
||||||
offerRecent(modCount, new RecentData<>(queryOptions, data));
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +216,6 @@ public abstract class AbstractCachedDataManager implements CachedDataManager {
|
|||||||
CompletableFuture.runAsync(() -> {
|
CompletableFuture.runAsync(() -> {
|
||||||
final C value = this.cacheLoader.apply(queryOptions);
|
final C value = this.cacheLoader.apply(queryOptions);
|
||||||
this.cache.put(queryOptions, value);
|
this.cache.put(queryOptions, value);
|
||||||
clearRecent();
|
|
||||||
}, CaffeineFactory.executor());
|
}, CaffeineFactory.executor());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,14 +225,9 @@ public abstract class AbstractCachedDataManager implements CachedDataManager {
|
|||||||
|
|
||||||
// invalidate the previous value until we're done recalculating
|
// invalidate the previous value until we're done recalculating
|
||||||
this.cache.remove(queryOptions);
|
this.cache.remove(queryOptions);
|
||||||
clearRecent();
|
|
||||||
|
|
||||||
// request recalculation from the cache
|
// request recalculation from the cache
|
||||||
return CompletableFuture.supplyAsync(() -> {
|
return CompletableFuture.supplyAsync(() -> this.cache.get(queryOptions), CaffeineFactory.executor());
|
||||||
C value = this.cache.get(queryOptions);
|
|
||||||
clearRecent();
|
|
||||||
return value;
|
|
||||||
}, CaffeineFactory.executor());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -261,13 +246,11 @@ public abstract class AbstractCachedDataManager implements CachedDataManager {
|
|||||||
public void invalidate(@NonNull QueryOptions queryOptions) {
|
public void invalidate(@NonNull QueryOptions queryOptions) {
|
||||||
Objects.requireNonNull(queryOptions, "queryOptions");
|
Objects.requireNonNull(queryOptions, "queryOptions");
|
||||||
this.cache.remove(queryOptions);
|
this.cache.remove(queryOptions);
|
||||||
clearRecent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invalidate() {
|
public void invalidate() {
|
||||||
this.cache.clear();
|
this.cache.clear();
|
||||||
clearRecent();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,14 +274,4 @@ public abstract class AbstractCachedDataManager implements CachedDataManager {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class RecentData<T> {
|
|
||||||
final QueryOptions queryOptions;
|
|
||||||
final T data;
|
|
||||||
|
|
||||||
RecentData(QueryOptions queryOptions, T data) {
|
|
||||||
this.queryOptions = queryOptions;
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user