Concurrency improvements

This commit is contained in:
Steffen Schaefer committed 2016-06-28 08:34:13 +02:00
1 parent 782a7427d4
commit 2afa0b76f2
2 files changed
+47 -13

No files matched your search

@@ -79,7 +79,7 @@ public class RaceLogFixTracker implements TrackingDataLoader {
private final SensorFixMapperFactory sensorFixMapperFactory;
private AtomicBoolean preemptiveStopRequested = new AtomicBoolean(false);
private AtomicBoolean stopRequested = new AtomicBoolean(false);
private final AbstractRaceChangeListener trackingTimesRaceChangeListener = new AbstractRaceChangeListener() {
private final AbstractRaceChangeListener raceChangeListener = new AbstractRaceChangeListener() {
@Override
public void startOfTrackingChanged(TimePoint oldStartOfTracking, TimePoint newStartOfTracking) {
if ((newStartOfTracking == null
@@ -311,7 +311,7 @@ public class RaceLogFixTracker implements TrackingDataLoader {
public void stop(boolean preemptive) {
preemptiveStopRequested.set(preemptive);
stopRequested.set(true);
trackedRace.removeListener(trackingTimesRaceChangeListener);
trackedRace.removeListener(raceChangeListener);
synchronized (knownRegattaLogs) {
knownRegattaLogs.forEach((log) -> log.removeListener(regattaLogEventVisitor));
knownRegattaLogs.clear();
@@ -328,12 +328,12 @@ public class RaceLogFixTracker implements TrackingDataLoader {
}
protected void startTracking() {
trackedRace.addListener(raceChangeListener);
final boolean hasRegattaLogs;
synchronized (knownRegattaLogs) {
trackedRace.getAttachedRegattaLogs().forEach(this::addRegattaLogUnlocked);
hasRegattaLogs = !knownRegattaLogs.isEmpty();
}
trackedRace.addListener(trackingTimesRaceChangeListener);
if (hasRegattaLogs) {
updateMappingsAndAddListeners();
}
@@ -1,5 +1,7 @@
package com.sap.sailing.domain.racelogtracking.impl.fixtracker;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
@@ -34,19 +36,23 @@ public class RaceLogFixTrackerManager implements TrackingDataLoader {
private final Owner owner;
/**
* We maintain our own collection that holds the RaceLogs. The known RaceLogs should by in sync with the ones that
* can be obtained from the TrackedRace. When stopping, there could be a concurrency issue that leads to a listener
* not being removed. This is prevented by remembering all RaceLogs to wich we attached a listener. So we can be
* sure to not produce a memory leak.
*/
private final Set<RaceLog> knownRaceLogs = new HashSet<>();
private RaceLogFixTracker tracker;
private final RaceChangeListener raceChangeListener = new AbstractRaceChangeListener() {
public void raceLogAttached(RaceLog raceLog) {
raceLog.addListener(raceLogEventVisitor);
updateDenotionState();
addRaceLog(raceLog);
}
public void raceLogDetached(RaceLog raceLog) {
raceLog.removeListener(raceLogEventVisitor);
updateDenotionState();
removeRaceLog(raceLog);
}
/**
@@ -99,8 +105,10 @@ public class RaceLogFixTrackerManager implements TrackingDataLoader {
trackedRace.addListener(raceChangeListener);
for (RaceLog raceLog : trackedRace.getAttachedRaceLogs()) {
raceLog.addListener(raceLogEventVisitor);
synchronized (knownRaceLogs) {
for (RaceLog raceLog : trackedRace.getAttachedRaceLogs()) {
addRaceLogUnlocked(raceLog);
}
}
updateDenotionState();
@@ -114,11 +122,37 @@ public class RaceLogFixTrackerManager implements TrackingDataLoader {
}
}
private void addRaceLog(RaceLog raceLog) {
synchronized (knownRaceLogs) {
addRaceLogUnlocked(raceLog);
}
updateDenotionState();
}
private void removeRaceLog(RaceLog raceLog) {
synchronized (knownRaceLogs) {
removeRaceLogUnlocked(raceLog);
}
updateDenotionState();
}
private void addRaceLogUnlocked(RaceLog raceLog) {
knownRaceLogs.add(raceLog);
raceLog.addListener(raceLogEventVisitor);
}
private void removeRaceLogUnlocked(RaceLog raceLog) {
raceLog.removeListener(raceLogEventVisitor);
knownRaceLogs.remove(raceLog);
}
public void stop(boolean preemptive) {
stopTracker(preemptive);
trackedRace.removeListener(raceChangeListener);
for (RaceLog raceLog : trackedRace.getAttachedRaceLogs()) {
raceLog.removeListener(raceLogEventVisitor);
synchronized (knownRaceLogs) {
for (RaceLog raceLog : trackedRace.getAttachedRaceLogs()) {
removeRaceLogUnlocked(raceLog);
}
}
}