mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-13 22:15:26 +00:00
using WeakValueCache for TracTrac DomainFactory;
let go of objects no longer strongly referenced by dedicated weak value caches Change-Id: I0b6ac5d198b689d5fc1ce8aa5eeeee3c39bce1cd
This commit is contained in:
1 parent
b26fbdaf0d
commit
576b22915a
3 files changed
+100
-8
No files matched your search
+5
-8
@@ -19,7 +19,6 @@ import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
@@ -85,6 +84,7 @@ import com.sap.sse.common.impl.AbstractColor;
|
||||
import com.sap.sse.common.impl.MillisecondsDurationImpl;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.util.WeakIdentityHashMap;
|
||||
import com.sap.sse.util.WeakValueCache;
|
||||
import com.tractrac.model.lib.api.data.IPosition;
|
||||
import com.tractrac.model.lib.api.event.CreateModelException;
|
||||
import com.tractrac.model.lib.api.event.ICompetitor;
|
||||
@@ -105,17 +105,14 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
|
||||
private final com.sap.sailing.domain.base.DomainFactory baseDomainFactory;
|
||||
|
||||
// TODO consider (re-)introducing WeakHashMaps for cache structures, but such that the cache is maintained as long as our domain objects are strongly referenced
|
||||
private final Map<TracTracControlPoint, com.sap.sailing.domain.base.ControlPoint> controlPointCache =
|
||||
new HashMap<TracTracControlPoint, com.sap.sailing.domain.base.ControlPoint>();
|
||||
private final WeakValueCache<TracTracControlPoint, com.sap.sailing.domain.base.ControlPoint> controlPointCache = new WeakValueCache<>(new HashMap<>());
|
||||
|
||||
private final Map<com.sap.sse.common.Util.Pair<String, UUID>, DynamicPerson> personCache = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Caches regattas by their name and their boat class's name
|
||||
*/
|
||||
private final Map<com.sap.sse.common.Util.Pair<String, String>, com.sap.sailing.domain.base.Regatta> regattaCache =
|
||||
new HashMap<com.sap.sse.common.Util.Pair<String, String>, com.sap.sailing.domain.base.Regatta>();
|
||||
private final WeakValueCache<com.sap.sse.common.Util.Pair<String, String>, com.sap.sailing.domain.base.Regatta> regattaCache = new WeakValueCache<>(new HashMap<>());
|
||||
|
||||
/**
|
||||
* A cache based on weak references to the TracTrac race, allowing for quick race lookup as long as the
|
||||
@@ -128,7 +125,7 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
* Maps from the TracTrac race UUIDs to the domain model's {@link RaceDefinition} objects that represent the race
|
||||
* identified by that UUID
|
||||
*/
|
||||
private final ConcurrentMap<UUID, RaceDefinition> raceCache = new ConcurrentHashMap<>();
|
||||
private final WeakValueCache<UUID, RaceDefinition> raceCache = new WeakValueCache<>(new ConcurrentHashMap<>());
|
||||
|
||||
private final MetadataParser metadataParser;
|
||||
|
||||
@@ -136,7 +133,7 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
this.baseDomainFactory = baseDomainFactory;
|
||||
this.metadataParser = new MetadataParserImpl();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MetadataParser getMetadataParser() {
|
||||
return metadataParser;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.sap.sse.util;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A weak reference that, when constructed, enters itself into a given map from where it can be removed
|
||||
* again using {@link #cleanUp}. The {@link #cleanUp()} method should be called after this weak reference
|
||||
* has been enqueued into the {@link ReferenceQueue} passed to the constructor.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
* @param <R>
|
||||
* the referent's type
|
||||
* @param <K>
|
||||
* the key's type
|
||||
*/
|
||||
public class WeakReferenceWithKey<K, R> extends WeakReference<R> {
|
||||
private final K key;
|
||||
private final Map<K, WeakReferenceWithKey<K, R>> map;
|
||||
private volatile boolean wasCleanedUp;
|
||||
|
||||
public WeakReferenceWithKey(K key, R referent, Map<K, WeakReferenceWithKey<K, R>> map, ReferenceQueue<? super R> q) {
|
||||
super(referent, q);
|
||||
this.wasCleanedUp = false;
|
||||
this.key = key;
|
||||
this.map = map;
|
||||
this.map.put(key, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assuming that this weak reference was entered into {@link #map} using key {@link
|
||||
*/
|
||||
public void cleanUp() {
|
||||
if (!wasCleanedUp) {
|
||||
this.map.remove(this.key);
|
||||
wasCleanedUp = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.sap.sse.util;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.Map;
|
||||
|
||||
public class WeakValueCache<K, V> {
|
||||
private final Map<K, WeakReferenceWithKey<K, V>> map;
|
||||
private final ReferenceQueue<V> queue;
|
||||
|
||||
public WeakValueCache(final Map<K, WeakReferenceWithKey<K, V>> map) {
|
||||
this.map = map;
|
||||
queue = new ReferenceQueue<>();
|
||||
}
|
||||
|
||||
public V get(K k) {
|
||||
purge();
|
||||
WeakReferenceWithKey<K, V> result = map.get(k);
|
||||
return result == null ? null : result.get();
|
||||
}
|
||||
|
||||
public V put(K k, V v) {
|
||||
purge();
|
||||
final V result;
|
||||
final WeakReferenceWithKey<K, V> old = map.get(k);
|
||||
if (old != null) {
|
||||
old.cleanUp();
|
||||
result = old.get();
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
map.put(k, new WeakReferenceWithKey<>(k, v, map, queue));
|
||||
return result;
|
||||
}
|
||||
|
||||
public V remove(K k) {
|
||||
purge();
|
||||
final V result;
|
||||
final WeakReferenceWithKey<K, V> ref = map.get(k);
|
||||
if (ref != null) {
|
||||
result = ref.get();
|
||||
ref.cleanUp();
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void purge() {
|
||||
WeakReferenceWithKey<?, ?> r;
|
||||
while ((r=(WeakReferenceWithKey<?, ?>) queue.poll()) != null) {
|
||||
r.cleanUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user