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