Refactor the way contexts are cached on all platforms (#1071)

Should fix memory leak issues on BungeeCord
This commit is contained in:
Luck
2018-06-27 00:17:53 +01:00
Unverified
parent ee13540d78
commit 08454d58d0
15 changed files with 285 additions and 62 deletions
@@ -25,8 +25,6 @@
package me.lucko.luckperms.common.contexts;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.Contexts;
@@ -62,12 +60,6 @@ public abstract class ContextManager<T> {
private final List<ContextCalculator<? super T>> calculators = new CopyOnWriteArrayList<>();
private final List<StaticContextCalculator> staticCalculators = new CopyOnWriteArrayList<>();
// caches the creation of cache instances. cache-ception.
// we want to encourage re-use of these instances, it's faster that way
private final LoadingCache<T, ContextsCache<T>> subjectCaches = Caffeine.newBuilder()
.weakKeys()
.build(key -> new ContextsCache<>(key, this));
// caches static context lookups
private final StaticLookupCache staticLookupCache = new StaticLookupCache();
@@ -129,12 +121,7 @@ public abstract class ContextManager<T> {
* @param subject the subject
* @return the cache
*/
public ContextsCache<T> getCacheFor(T subject) {
if (subject == null) {
throw new NullPointerException("subject");
}
return this.subjectCaches.get(subject);
}
public abstract ContextsSupplier getCacheFor(T subject);
/**
* Gets the contexts from the static calculators in this manager.
@@ -228,18 +215,9 @@ public abstract class ContextManager<T> {
*
* @param subject the subject
*/
public void invalidateCache(T subject) {
if (subject == null) {
throw new NullPointerException("subject");
}
public abstract void invalidateCache(T subject);
ContextsCache<T> cache = this.subjectCaches.getIfPresent(subject);
if (cache != null) {
cache.invalidate();
}
}
Contexts calculate(T subject) {
protected Contexts calculate(T subject) {
MutableContextSet accumulator = MutableContextSet.create();
for (ContextCalculator<? super T> calculator : ContextManager.this.calculators) {
@@ -34,12 +34,11 @@ import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
/**
* Extension of {@link ContextManager} that implements an expiring lookup cache
* per player.
* Implementation of {@link ContextsSupplier} that caches results.
*
* @param <T> the player type
*/
public final class ContextsCache<T> extends ExpiringCache<Contexts> {
public final class ContextsCache<T> extends ExpiringCache<Contexts> implements ContextsSupplier {
private final T subject;
private final ContextManager<T> contextManager;
@@ -55,10 +54,12 @@ public final class ContextsCache<T> extends ExpiringCache<Contexts> {
return this.contextManager.calculate(this.subject);
}
@Override
public Contexts getContexts() {
return get();
}
@Override
public ImmutableContextSet getContextSet() {
// this is actually already immutable, but the Contexts method signature returns the interface.
// using the makeImmutable method is faster than casting
@@ -0,0 +1,40 @@
/*
* 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.contexts;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.context.ImmutableContextSet;
/**
* Supplies contexts for a given subject.
*/
public interface ContextsSupplier {
Contexts getContexts();
ImmutableContextSet getContextSet();
}