clone listener set into array, moving listener notification out of synchronized block, trying to increase concurrency

This commit is contained in:
Axel Uhl
2012-04-09 12:43:32 +02:00
parent 3a718acd89
commit c1eb61a617
2 changed files with 94 additions and 62 deletions
@@ -16,6 +16,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.logging.Logger;
import com.sap.sailing.domain.base.Boat;
@@ -92,6 +93,14 @@ public class DomainFactoryImpl implements DomainFactory {
private final Map<Pair<String, String>, com.sap.sailing.domain.base.Event> eventCache =
new HashMap<Pair<String, String>, com.sap.sailing.domain.base.Event>();
/**
* A cache based on weak references to the TracTrac event, allowing for quick Event lookup as long as the
* TracTrac event remains referenced. This is intended to reduce the number of times the dominant boat
* class needs to be determined for an event. Synchronization for additions / removals is tied to the
* synchronization for {@link #eventCache}.
*/
private final WeakHashMap<com.tractrac.clientmodule.Event, Event> weakEventCache = new WeakHashMap<>();
private final Map<Race, RaceDefinition> raceCache = new HashMap<Race, RaceDefinition>();
private final Set<String> mayStartWithNoUpwindLeg;
@@ -254,16 +263,24 @@ public class DomainFactoryImpl implements DomainFactory {
// This means that currently it is permissible to assume that we'll get at most one
// boat class per TracTrac event. Generally, however, we have to assume that
// one TracTrac event may map to multiple domain Event objects with one BoatClass each
Collection<CompetitorClass> competitorClassList = new ArrayList<CompetitorClass>();
for (com.tractrac.clientmodule.Competitor c : event.getCompetitorList()) {
competitorClassList.add(c.getCompetitorClass());
}
BoatClass boatClass = getDominantBoatClass(competitorClassList);
Pair<String, String> key = new Pair<String, String>(event.getName(), boatClass==null?null:boatClass.getName());
Event result = eventCache.get(key);
// try a quick look-up in the weak cache using the TracTrac event as key; only if that delivers no result,
// compute the dominant boat class which requires a lot more effort
Event result = weakEventCache.get(event);
if (result == null) {
result = new EventImpl(event.getName(), boatClass);
eventCache.put(key, result);
Collection<CompetitorClass> competitorClassList = new ArrayList<CompetitorClass>();
for (com.tractrac.clientmodule.Competitor c : event.getCompetitorList()) {
competitorClassList.add(c.getCompetitorClass());
}
BoatClass boatClass = getDominantBoatClass(competitorClassList);
Pair<String, String> key = new Pair<String, String>(event.getName(), boatClass == null ? null
: boatClass.getName());
result = eventCache.get(key);
if (result == null) {
result = new EventImpl(event.getName(), boatClass);
eventCache.put(key, result);
weakEventCache.put(event, result);
}
}
return result;
}
@@ -338,6 +355,7 @@ public class DomainFactoryImpl implements DomainFactory {
event.removeRace(raceDefinition);
if (oldSize > 0 && Util.size(event.getAllRaces()) == 0) {
eventCache.remove(key);
weakEventCache.remove(tractracEvent);
}
TrackedEvent trackedEvent = trackedEventRegistry.getTrackedEvent(event);
if (trackedEvent != null) {
@@ -147,96 +147,110 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
}
private void notifyListeners(GPSFix fix, Buoy buoy) {
RaceChangeListener[] listeners;
synchronized (getListeners()) {
for (RaceChangeListener listener : getListeners()) {
try {
listener.buoyPositionChanged(fix, buoy);
} catch (Throwable t) {
logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + t.getMessage());
logger.throwing(DynamicTrackedRaceImpl.class.getName(), "notifyListeners(GPSFix, Competitor)", t);
}
listeners = getListeners().toArray(new RaceChangeListener[getListeners().size()]);
}
for (RaceChangeListener listener : listeners) {
try {
listener.buoyPositionChanged(fix, buoy);
} catch (Throwable t) {
logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + t.getMessage());
logger.throwing(DynamicTrackedRaceImpl.class.getName(), "notifyListeners(GPSFix, Competitor)", t);
}
}
}
private void notifyListeners(GPSFix fix, Competitor competitor) {
RaceChangeListener[] listeners;
synchronized (getListeners()) {
for (RaceChangeListener listener : getListeners()) {
try {
listener.competitorPositionChanged(fix, competitor);
} catch (Throwable t) {
logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + t.getMessage());
logger.throwing(DynamicTrackedRaceImpl.class.getName(), "notifyListeners(GPSFix, Competitor)", t);
}
listeners = getListeners().toArray(new RaceChangeListener[getListeners().size()]);
}
for (RaceChangeListener listener : listeners) {
try {
listener.competitorPositionChanged(fix, competitor);
} catch (Throwable t) {
logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + t.getMessage());
logger.throwing(DynamicTrackedRaceImpl.class.getName(), "notifyListeners(GPSFix, Competitor)", t);
}
}
}
private void notifyListeners(Wind wind) {
RaceChangeListener[] listeners;
synchronized (getListeners()) {
for (RaceChangeListener listener : getListeners()) {
try {
listener.windDataReceived(wind);
} catch (Throwable t) {
logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + t.getMessage());
logger.throwing(DynamicTrackedRaceImpl.class.getName(), "notifyListeners(Wind)", t);
}
listeners = getListeners().toArray(new RaceChangeListener[getListeners().size()]);
}
for (RaceChangeListener listener : listeners) {
try {
listener.windDataReceived(wind);
} catch (Throwable t) {
logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + t.getMessage());
logger.throwing(DynamicTrackedRaceImpl.class.getName(), "notifyListeners(Wind)", t);
}
}
}
private void notifyListenersSpeedAveragingChanged(long oldMillisecondsOverWhichToAverageSpeed, long newMillisecondsOverWhichToAverageSpeed) {
RaceChangeListener[] listeners;
synchronized (getListeners()) {
for (RaceChangeListener listener : getListeners()) {
try {
listener.speedAveragingChanged(oldMillisecondsOverWhichToAverageSpeed,
newMillisecondsOverWhichToAverageSpeed);
} catch (Throwable t) {
logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + t.getMessage());
logger.throwing(DynamicTrackedRaceImpl.class.getName(),
"notifyListenersSpeedAveragingChanged(long, long)", t);
}
listeners = getListeners().toArray(new RaceChangeListener[getListeners().size()]);
}
for (RaceChangeListener listener : listeners) {
try {
listener.speedAveragingChanged(oldMillisecondsOverWhichToAverageSpeed,
newMillisecondsOverWhichToAverageSpeed);
} catch (Throwable t) {
logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + t.getMessage());
logger.throwing(DynamicTrackedRaceImpl.class.getName(),
"notifyListenersSpeedAveragingChanged(long, long)", t);
}
}
}
private void notifyListenersWindAveragingChanged(long oldMillisecondsOverWhichToAverageWind, long newMillisecondsOverWhichToAverageWind) {
RaceChangeListener[] listeners;
synchronized (getListeners()) {
for (RaceChangeListener listener : getListeners()) {
try {
listener.windAveragingChanged(oldMillisecondsOverWhichToAverageWind,
newMillisecondsOverWhichToAverageWind);
} catch (Throwable t) {
logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + t.getMessage());
logger.throwing(DynamicTrackedRaceImpl.class.getName(),
"notifyListenersWindAveragingChanged(long, long)", t);
}
listeners = getListeners().toArray(new RaceChangeListener[getListeners().size()]);
}
for (RaceChangeListener listener : listeners) {
try {
listener.windAveragingChanged(oldMillisecondsOverWhichToAverageWind,
newMillisecondsOverWhichToAverageWind);
} catch (Throwable t) {
logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + t.getMessage());
logger.throwing(DynamicTrackedRaceImpl.class.getName(),
"notifyListenersWindAveragingChanged(long, long)", t);
}
}
}
private void notifyListenersWindRemoved(Wind wind) {
RaceChangeListener[] listeners;
synchronized (getListeners()) {
for (RaceChangeListener listener : getListeners()) {
try {
listener.windDataRemoved(wind);
} catch (Throwable t) {
logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + t.getMessage());
logger.throwing(DynamicTrackedRaceImpl.class.getName(), "notifyListenersWindRemoved(Wind)", t);
}
listeners = getListeners().toArray(new RaceChangeListener[getListeners().size()]);
}
for (RaceChangeListener listener : listeners) {
try {
listener.windDataRemoved(wind);
} catch (Throwable t) {
logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + t.getMessage());
logger.throwing(DynamicTrackedRaceImpl.class.getName(), "notifyListenersWindRemoved(Wind)", t);
}
}
}
private void notifyListeners(MarkPassing oldMarkPassing, MarkPassing markPassing) {
RaceChangeListener[] listeners;
synchronized (getListeners()) {
for (RaceChangeListener listener : getListeners()) {
try {
listener.markPassingReceived(oldMarkPassing, markPassing);
} catch (Throwable t) {
logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + t.getMessage());
logger.throwing(DynamicTrackedRaceImpl.class.getName(), "notifyListeners(MarkPassing)", t);
}
listeners = getListeners().toArray(new RaceChangeListener[getListeners().size()]);
}
for (RaceChangeListener listener : listeners) {
try {
listener.markPassingReceived(oldMarkPassing, markPassing);
} catch (Throwable t) {
logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + t.getMessage());
logger.throwing(DynamicTrackedRaceImpl.class.getName(), "notifyListeners(MarkPassing)", t);
}
}
}