using a ConcurrentHashMap with the new IdentityWrapper to avoid excessive synchronization on markPassingLocks; see bug 3380

This commit is contained in:
Axel Uhl committed 2015-12-03 21:17:01 +01:00
1 parent a3613c6f23
commit 6157309227
2 files changed
+45 -10

No files matched your search

@@ -13,7 +13,6 @@ import java.util.ConcurrentModificationException;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
@@ -154,6 +153,7 @@ import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.concurrent.LockUtil;
import com.sap.sse.concurrent.NamedReentrantReadWriteLock;
import com.sap.sse.util.IdentityWrapper;
import com.sap.sse.util.SmartFutureCache;
import com.sap.sse.util.SmartFutureCache.AbstractCacheUpdater;
import com.sap.sse.util.SmartFutureCache.EmptyUpdateInterval;
@@ -354,7 +354,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
*/
private final NamedReentrantReadWriteLock loadingFromGPSFixStoreLock;
private final Map<Iterable<MarkPassing>, NamedReentrantReadWriteLock> locksForMarkPassings;
private final ConcurrentHashMap<IdentityWrapper<Iterable<MarkPassing>>, NamedReentrantReadWriteLock> locksForMarkPassings;
/**
* Caches wind requests for a few seconds to accelerate access in live mode
@@ -412,7 +412,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
rankingMetric = rankingMetricConstructor.apply(this);
raceStates = new WeakHashMap<>();
shortTimeWindCache = new ShortTimeWindCache(this, millisecondsOverWhichToAverageWind / 2);
locksForMarkPassings = new IdentityHashMap<>();
locksForMarkPassings = new ConcurrentHashMap<IdentityWrapper<Iterable<MarkPassing>>, NamedReentrantReadWriteLock>();
attachedRaceLogs = new ConcurrentHashMap<>();
attachedRegattaLogs = new ConcurrentHashMap<>();
attachedRaceExecutionOrderProviders = new ConcurrentHashMap<>();
@@ -2058,15 +2058,19 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
}
protected NamedReentrantReadWriteLock getMarkPassingsLock(Iterable<MarkPassing> markPassings) {
synchronized (locksForMarkPassings) {
NamedReentrantReadWriteLock lock = locksForMarkPassings.get(markPassings);
if (lock == null) {
lock = new NamedReentrantReadWriteLock("mark passings lock for tracked race " + getRace().getName(), /* fair */
false);
locksForMarkPassings.put(markPassings, lock);
final IdentityWrapper<Iterable<MarkPassing>> markPassingsIdentity = new IdentityWrapper<>(markPassings);
NamedReentrantReadWriteLock lock = locksForMarkPassings.get(markPassingsIdentity);
if (lock == null) {
synchronized (locksForMarkPassings) {
lock = locksForMarkPassings.get(markPassingsIdentity);
if (lock == null) {
lock = new NamedReentrantReadWriteLock(
"mark passings lock for tracked race " + getRace().getName(), /* fair */false);
locksForMarkPassings.put(markPassingsIdentity, lock);
}
}
return lock;
}
return lock;
}
private void updateStartToNextMarkCacheInvalidationCacheListenersAfterWaypointRemoved(int zeroBasedIndex,
@@ -0,0 +1,31 @@
package com.sap.sse.util;
/**
* Implements {@link Object#equals(Object)} and {@link Object#hashCode()} based on the wrapped object's
* identity, no matter what the object itself defines as {@code equals} and {@code hashCode}.
*
* @author Axel Uhl (D043530)
*
*/
public class IdentityWrapper<T> {
private final T t;
public IdentityWrapper(T t) {
this.t = t;
}
@Override
public int hashCode() {
return System.identityHashCode(t);
}
@Override
public boolean equals(Object obj) {
return (obj instanceof IdentityWrapper<?>) ? ((IdentityWrapper<?>) obj).t == this.t : obj == t;
}
@Override
public String toString() {
return "IdentityWrapper for "+t;
}
}