fixing bug 820: another concurrent modification exception, this time unsynchronized access to markPassingsTimes cache

This commit is contained in:
Axel Uhl committed 2012-06-26 13:07:02 +02:00
1 parent e99f58e393
commit fd08026e18
3 files changed
+50 -33

No files matched your search

@@ -121,6 +121,9 @@ public abstract class AbstractReceiverWithQueue<A, B, C> implements Runnable, Re
e.printStackTrace(); e.printStackTrace();
} }
} }
if (simulator != null) {
simulator.stop();
}
} }
@Override @Override
@@ -32,6 +32,7 @@ public class Simulator {
private WindStore windStore; private WindStore windStore;
private long advanceInMillis = -1; private long advanceInMillis = -1;
private Timer timer = new Timer("Timer for TracTrac Simulator"); private Timer timer = new Timer("Timer for TracTrac Simulator");
private boolean stopped;
/** /**
* Creates a wind store which replays the wind store events against a tracked race, correcting the wind fixes with * Creates a wind store which replays the wind store events against a tracked race, correcting the wind fixes with
@@ -70,6 +71,9 @@ public class Simulator {
@Override @Override
public void run() { public void run() {
for (Wind wind : windSourceAndTrack.getValue().getRawFixes()) { for (Wind wind : windSourceAndTrack.getValue().getRawFixes()) {
if (stopped) {
break;
}
trackedRace.recordWind(delayWind(wind), windSourceAndTrack.getKey()); trackedRace.recordWind(delayWind(wind), windSourceAndTrack.getKey());
} }
} }
@@ -77,6 +81,10 @@ public class Simulator {
} }
} }
public void stop() {
stopped = true;
}
private Wind delayWind(Wind wind) { private Wind delayWind(Wind wind) {
TimePoint delayedTimePoint = delay(wind.getTimePoint()); TimePoint delayedTimePoint = delay(wind.getTimePoint());
return new WindImpl(wind.getPosition(), delayedTimePoint, new KnotSpeedWithBearingImpl(wind.getKnots(), wind.getBearing())); return new WindImpl(wind.getPosition(), delayedTimePoint, new KnotSpeedWithBearingImpl(wind.getKnots(), wind.getBearing()));
@@ -329,7 +329,9 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
} }
protected void invalidateMarkPassingTimes() { protected void invalidateMarkPassingTimes() {
markPassingsTimes.clear(); synchronized (markPassingsTimes) {
markPassingsTimes.clear();
}
} }
/** /**
@@ -481,45 +483,49 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
@Override @Override
public Iterable<Pair<Waypoint, Pair<TimePoint, TimePoint>>> getMarkPassingsTimes() { public Iterable<Pair<Waypoint, Pair<TimePoint, TimePoint>>> getMarkPassingsTimes() {
if (markPassingsTimes.isEmpty()) { synchronized (markPassingsTimes) {
int wayPointNumber = 1; if (markPassingsTimes.isEmpty()) {
// Remark: sometimes it can happen that a mark passing with a wrong time stamp breaks the right time order int wayPointNumber = 1;
// of the waypoint times // Remark: sometimes it can happen that a mark passing with a wrong time stamp breaks the right time
Date previousLegPassingTime = null; // order of the waypoint times
for (Waypoint waypoint : getRace().getCourse().getWaypoints()) { Date previousLegPassingTime = null;
TimePoint firstPassingTime = null; for (Waypoint waypoint : getRace().getCourse().getWaypoints()) {
TimePoint lastPassingTime = null; TimePoint firstPassingTime = null;
if (wayPointNumber == 1) { TimePoint lastPassingTime = null;
// For the first leg the use of "firstPassingDate" is not correct, if (wayPointNumber == 1) {
// because boats can pass the start line before the actual start; // For the first leg the use of "firstPassingDate" is not correct,
// therefore we are using the calculated start time here // because boats can pass the start line before the actual start;
firstPassingTime = getStartOfRace(); // therefore we are using the calculated start time here
} else { firstPassingTime = getStartOfRace();
NavigableSet<MarkPassing> markPassings = getMarkPassingsInOrderAsNavigableSet(waypoint); } else {
if (markPassings != null && !markPassings.isEmpty()) { NavigableSet<MarkPassing> markPassings = getMarkPassingsInOrderAsNavigableSet(waypoint);
// ensure the leg times are in the right time order; there may perhaps be left-overs for marks to be if (markPassings != null && !markPassings.isEmpty()) {
// reached later that // ensure the leg times are in the right time order; there may perhaps be left-overs for
// claim it has been passed in the past which may have been an accidental tracker read-out; // marks to be reached later that
// the results of getMarkPassingsInOrder(to) has by definition an ascending time-point ordering // claim it has been passed in the past which may have been an accidental tracker read-out;
synchronized (markPassings) { // the results of getMarkPassingsInOrder(to) has by definition an ascending time-point
for (MarkPassing currentMarkPassing : markPassings) { // ordering
Date currentPassingDate = currentMarkPassing.getTimePoint().asDate(); synchronized (markPassings) {
if (previousLegPassingTime == null || currentPassingDate.after(previousLegPassingTime)) { for (MarkPassing currentMarkPassing : markPassings) {
firstPassingTime = currentMarkPassing.getTimePoint(); Date currentPassingDate = currentMarkPassing.getTimePoint().asDate();
previousLegPassingTime = currentPassingDate; if (previousLegPassingTime == null
break; || currentPassingDate.after(previousLegPassingTime)) {
firstPassingTime = currentMarkPassing.getTimePoint();
previousLegPassingTime = currentPassingDate;
break;
}
} }
} }
} }
} }
Pair<TimePoint, TimePoint> timesPair = new Pair<TimePoint, TimePoint>(firstPassingTime,
lastPassingTime);
markPassingsTimes.add(new Pair<Waypoint, Pair<TimePoint, TimePoint>>(waypoint, timesPair));
wayPointNumber++;
} }
Pair<TimePoint, TimePoint> timesPair = new Pair<TimePoint, TimePoint>(firstPassingTime, lastPassingTime);
markPassingsTimes.add(new Pair<Waypoint, Pair<TimePoint, TimePoint>>(waypoint, timesPair));
wayPointNumber++;
} }
return markPassingsTimes;
} }
return markPassingsTimes;
} }
@Override @Override