mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-02 17:19:37 +00:00
fixing bug 820: another concurrent modification exception, this time unsynchronized access to markPassingsTimes cache
This commit is contained in:
1 parent
e99f58e393
commit
fd08026e18
3 files changed
+50
-33
No files matched your search
+3
@@ -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
|
||||||
|
|||||||
+8
@@ -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()));
|
||||||
|
|||||||
+39
-33
@@ -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
|
||||||
|
|||||||
Reference in new issue
Block a user