diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteRecalculationThreadHelper.java b/OsmAnd/src/net/osmand/plus/routing/RouteRecalculationHelper.java similarity index 71% rename from OsmAnd/src/net/osmand/plus/routing/RouteRecalculationThreadHelper.java rename to OsmAnd/src/net/osmand/plus/routing/RouteRecalculationHelper.java index 340d13fedf..175003fe18 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteRecalculationThreadHelper.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteRecalculationHelper.java @@ -10,11 +10,19 @@ import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.router.RouteCalculationProgress; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import static net.osmand.plus.notifications.OsmandNotification.NotificationType.NAVIGATION; -class RouteRecalculationThreadHelper { +class RouteRecalculationHelper { private static final int RECALCULATE_THRESHOLD_COUNT_CAUSING_FULL_RECALCULATE = 3; private static final int RECALCULATE_THRESHOLD_CAUSING_FULL_RECALCULATE_INTERVAL = 2 * 60 * 1000; @@ -22,17 +30,19 @@ class RouteRecalculationThreadHelper { private final OsmandApplication app; private final RoutingHelper routingHelper; - private Thread currentRunningJob; + private final ExecutorService executor = new RouteRecalculationExecutor(); + private final Map, RouteRecalculationTask> tasksMap = new LinkedHashMap<>(); + private RouteRecalculationTask lastTask; + private long lastTimeEvaluatedRoute = 0; private String lastRouteCalcError; private String lastRouteCalcErrorShort; private long recalculateCountInInterval = 0; private int evalWaitInterval = 0; - private boolean waitingNextJob; private RouteCalculationProgressCallback progressRoute; - RouteRecalculationThreadHelper(@NonNull RoutingHelper routingHelper) { + RouteRecalculationHelper(@NonNull RoutingHelper routingHelper) { this.routingHelper = routingHelper; this.app = routingHelper.getApplication(); } @@ -50,7 +60,14 @@ class RouteRecalculationThreadHelper { } boolean isRouteBeingCalculated() { - return currentRunningJob instanceof RouteRecalculationThread || waitingNextJob; + synchronized (routingHelper) { + for (Future future : tasksMap.keySet()) { + if (!future.isDone()) { + return true; + } + } + } + return false; } void resetEvalWaitInterval() { @@ -58,21 +75,28 @@ class RouteRecalculationThreadHelper { } void stopCalculation() { - Thread job = currentRunningJob; - if (job instanceof RouteRecalculationThread) { - ((RouteRecalculationThread) job).stopCalculation(); + synchronized (routingHelper) { + for (Entry, RouteRecalculationTask> taskFuture : tasksMap.entrySet()) { + taskFuture.getValue().stopCalculation(); + taskFuture.getKey().cancel(false); + } } } - void stopCalculationIfParamsChanged() { - Thread job = currentRunningJob; - if (job instanceof RouteRecalculationThread) { - RouteRecalculationThread thread = (RouteRecalculationThread) job; - if (!thread.isParamsChanged()) { - thread.stopCalculation(); + void stopCalculationIfParamsNotChanged() { + synchronized (routingHelper) { + boolean hasPendingTasks = tasksMap.isEmpty(); + for (Entry, RouteRecalculationTask> taskFuture : tasksMap.entrySet()) { + RouteRecalculationTask task = taskFuture.getValue(); + if (!task.isParamsChanged()) { + taskFuture.getKey().cancel(false); + task.stopCalculation(); + } } - if (isFollowingMode()) { - getVoiceRouter().announceBackOnRoute(); + if (hasPendingTasks) { + if (isFollowingMode()) { + getVoiceRouter().announceBackOnRoute(); + } } } } @@ -130,8 +154,6 @@ class RouteRecalculationThreadHelper { } } - - // trigger voice prompt only if new route is in forward direction // If route is in wrong direction after one more setLocation it will be recalculated if (!wrongMovementDirection || newRoute) { @@ -144,18 +166,15 @@ class RouteRecalculationThreadHelper { void startRouteCalculationThread(RouteCalculationParams params, boolean paramsChanged, boolean updateProgress) { synchronized (routingHelper) { - final Thread prevRunningJob = currentRunningJob; getSettings().LAST_ROUTE_APPLICATION_MODE.set(getAppMode()); - RouteRecalculationThread newThread = new RouteRecalculationThread("Calculating route", params, paramsChanged); - currentRunningJob = newThread; + RouteRecalculationTask newTask = new RouteRecalculationTask(this, params, paramsChanged); + lastTask = newTask; startProgress(params); if (updateProgress) { updateProgress(params); } - if (prevRunningJob != null) { - newThread.setWaitPrevJob(prevRunningJob); - } - currentRunningJob.start(); + Future future = executor.submit(newTask); + tasksMap.put(future, newTask); } } @@ -165,7 +184,7 @@ class RouteRecalculationThreadHelper { return; } // do not evaluate very often - if ((currentRunningJob == null && System.currentTimeMillis() - lastTimeEvaluatedRoute > evalWaitInterval) + if ((!isRouteBeingCalculated() && System.currentTimeMillis() - lastTimeEvaluatedRoute > evalWaitInterval) || paramsChanged || !onlyStartPointChanged) { if (System.currentTimeMillis() - lastTimeEvaluatedRoute < RECALCULATE_THRESHOLD_CAUSING_FULL_RECALCULATE_INTERVAL) { recalculateCountInInterval++; @@ -234,11 +253,7 @@ class RouteRecalculationThreadHelper { public void run() { RouteCalculationProgress calculationProgress = params.calculationProgress; if (isRouteBeingCalculated()) { - Thread t = currentRunningJob; - if (t instanceof RouteRecalculationThread && ((RouteRecalculationThread) t).params != params) { - // different calculation started - return; - } else { + if (lastTask != null && lastTask.params == params) { progressRoute.updateProgress((int) calculationProgress.getLinearProgress()); if (calculationProgress.requestPrivateAccessRouting) { progressRoute.requestPrivateAccessRouting(); @@ -268,23 +283,21 @@ class RouteRecalculationThreadHelper { } } - private void showMessage(final String msg) { - app.runInUIThread(new Runnable() { - @Override - public void run() { - app.showToastMessage(msg); - } - }); - } - - class RouteRecalculationThread extends Thread { + private static class RouteRecalculationTask implements Runnable { + private final RouteRecalculationHelper routingThreadHelper; + private final RoutingHelper routingHelper; private final RouteCalculationParams params; private final boolean paramsChanged; - private Thread prevRunningJob; - public RouteRecalculationThread(String name, RouteCalculationParams params, boolean paramsChanged) { - super(name); + String routeCalcError; + String routeCalcErrorShort; + int evalWaitInterval = 0; + + public RouteRecalculationTask(@NonNull RouteRecalculationHelper routingThreadHelper, + @NonNull RouteCalculationParams params, boolean paramsChanged) { + this.routingThreadHelper = routingThreadHelper; + this.routingHelper = routingThreadHelper.routingHelper; this.params = params; this.paramsChanged = paramsChanged; if (params.calculationProgress == null) { @@ -300,39 +313,26 @@ class RouteRecalculationThreadHelper { params.calculationProgress.isCancelled = true; } + private OsmandSettings getSettings() { + return routingHelper.getSettings(); + } + + private void showMessage(final String msg) { + final OsmandApplication app = routingHelper.getApplication(); + app.runInUIThread(new Runnable() { + @Override + public void run() { + app.showToastMessage(msg); + } + }); + } @Override public void run() { - synchronized (routingHelper) { - routingHelper.resetRouteWasFinished(); - currentRunningJob = this; - waitingNextJob = prevRunningJob != null; - } - if (prevRunningJob != null) { - while (prevRunningJob.isAlive()) { - try { - Thread.sleep(50); - } catch (InterruptedException e) { - // ignore - } - } - synchronized (routingHelper) { - if (params.calculationProgress.isCancelled) { - return; - } - currentRunningJob = this; - waitingNextJob = false; - } - } - lastRouteCalcError = null; - lastRouteCalcErrorShort = null; RouteProvider provider = routingHelper.getProvider(); OsmandSettings settings = getSettings(); RouteCalculationResult res = provider.calculateRouteImpl(params); if (params.calculationProgress.isCancelled) { - synchronized (routingHelper) { - currentRunningJob = null; - } return; } final boolean onlineSourceWithoutInternet = !res.isCalculated() && @@ -353,37 +353,54 @@ class RouteRecalculationThreadHelper { params.resultListener.onRouteCalculated(res); } } else { - evalWaitInterval = Math.max(3000, evalWaitInterval * 3 / 2); // for Issue #3899 + evalWaitInterval = Math.max(3000, routingThreadHelper.evalWaitInterval * 3 / 2); // for Issue #3899 evalWaitInterval = Math.min(evalWaitInterval, 120000); } - currentRunningJob = null; } + OsmandApplication app = routingHelper.getApplication(); if (res.isCalculated()) { if (!params.inSnapToRoadMode && !params.inPublicTransportMode) { - setNewRoute(prev, res, params.start); + routingThreadHelper.setNewRoute(prev, res, params.start); } } else if (onlineSourceWithoutInternet) { - lastRouteCalcError = app.getString(R.string.error_calculating_route) + routeCalcError = app.getString(R.string.error_calculating_route) + ":\n" + app.getString(R.string.internet_connection_required_for_online_route); - lastRouteCalcErrorShort = app.getString(R.string.error_calculating_route); - showMessage(lastRouteCalcError); //$NON-NLS-1$ + routeCalcErrorShort = app.getString(R.string.error_calculating_route); + showMessage(routeCalcError); } else { if (res.getErrorMessage() != null) { - lastRouteCalcError = app.getString(R.string.error_calculating_route) + ":\n" + res.getErrorMessage(); - lastRouteCalcErrorShort = app.getString(R.string.error_calculating_route); - showMessage(lastRouteCalcError); //$NON-NLS-1$ + routeCalcError = app.getString(R.string.error_calculating_route) + ":\n" + res.getErrorMessage(); + routeCalcErrorShort = app.getString(R.string.error_calculating_route); } else { - lastRouteCalcError = app.getString(R.string.empty_route_calculated); - lastRouteCalcErrorShort = app.getString(R.string.empty_route_calculated); - showMessage(lastRouteCalcError); + routeCalcError = app.getString(R.string.empty_route_calculated); + routeCalcErrorShort = app.getString(R.string.empty_route_calculated); } + showMessage(routeCalcError); } app.getNotificationHelper().refreshNotification(NAVIGATION); - lastTimeEvaluatedRoute = System.currentTimeMillis(); + } + } + + private class RouteRecalculationExecutor extends ThreadPoolExecutor { + + public RouteRecalculationExecutor() { + super(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); } - public void setWaitPrevJob(Thread prevRunningJob) { - this.prevRunningJob = prevRunningJob; + protected void afterExecute(Runnable r, Throwable t) { + super.afterExecute(r, t); + RouteRecalculationTask task = null; + synchronized (routingHelper) { + if (r instanceof Future) { + task = tasksMap.remove(r); + } + } + if (t == null && task != null) { + evalWaitInterval = task.evalWaitInterval; + lastRouteCalcError = task.routeCalcError; + lastRouteCalcErrorShort = task.routeCalcErrorShort; + } + lastTimeEvaluatedRoute = System.currentTimeMillis(); } } } diff --git a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java index 179318790e..e080f7b3bd 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java +++ b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java @@ -54,7 +54,7 @@ public class RoutingHelper { private OsmandSettings settings; private final RouteProvider provider; private final VoiceRouter voiceRouter; - private final RouteRecalculationThreadHelper routeRecalculationHelper; + private final RouteRecalculationHelper routeRecalculationHelper; private final TransportRoutingHelper transportRoutingHelper; private boolean isFollowingMode = false; @@ -94,7 +94,7 @@ public class RoutingHelper { settings = context.getSettings(); voiceRouter = new VoiceRouter(this); provider = new RouteProvider(); - routeRecalculationHelper = new RouteRecalculationThreadHelper(this); + routeRecalculationHelper = new RouteRecalculationHelper(this); transportRoutingHelper = context.getTransportRoutingHelper(); transportRoutingHelper.setRoutingHelper(this); setAppMode(settings.APPLICATION_MODE.get()); @@ -505,7 +505,7 @@ public class RoutingHelper { routeRecalculationHelper.recalculateRouteInBackground(currentLocation, finalLocation, intermediatePoints, currentGPXRoute, previousRoute.isCalculated() ? previousRoute : null, false, !targetPointsChanged); } else { - routeRecalculationHelper.stopCalculationIfParamsChanged(); + routeRecalculationHelper.stopCalculationIfParamsNotChanged(); } double projectDist = mode != null && mode.hasFastSpeed() ? posTolerance : posTolerance / 2; diff --git a/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java b/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java index b5a90da2ce..08da774f27 100644 --- a/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java +++ b/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java @@ -13,37 +13,42 @@ import net.osmand.binary.BinaryMapIndexReader; import net.osmand.data.LatLon; import net.osmand.data.QuadRect; import net.osmand.osm.edit.Node; -import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; -import net.osmand.plus.settings.backend.CommonPreference; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.render.NativeOsmandLibrary; import net.osmand.plus.routing.RouteCalculationParams.RouteCalculationResultListener; import net.osmand.plus.routing.RouteProvider.RouteService; +import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.plus.settings.backend.CommonPreference; +import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.router.GeneralRouter; - +import net.osmand.router.NativeTransportRoutingResult; import net.osmand.router.RouteCalculationProgress; import net.osmand.router.RoutingConfiguration; import net.osmand.router.TransportRoutePlanner; -import net.osmand.router.TransportRouteResult; import net.osmand.router.TransportRoutePlanner.TransportRouteResultSegment; -import net.osmand.router.TransportRoutingContext; +import net.osmand.router.TransportRouteResult; import net.osmand.router.TransportRoutingConfiguration; -import net.osmand.router.NativeTransportRoutingResult; +import net.osmand.router.TransportRoutingContext; import net.osmand.util.MapUtils; import java.io.IOException; import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.TreeMap; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import static net.osmand.plus.notifications.OsmandNotification.NotificationType.NAVIGATION; @@ -53,10 +58,14 @@ public class TransportRoutingHelper { private List> listeners = new LinkedList<>(); - private OsmandApplication app; + private final OsmandApplication app; private ApplicationMode applicationMode = ApplicationMode.PUBLIC_TRANSPORT; private RoutingHelper routingHelper; + private final ExecutorService executor = new RouteRecalculationExecutor(); + private final Map, RouteRecalculationTask> tasksMap = new LinkedHashMap<>(); + private RouteRecalculationTask lastTask; + private List routes; private Map, RouteCalculationResult> walkingRouteSegments; private int currentRoute = -1; @@ -64,11 +73,9 @@ public class TransportRoutingHelper { private LatLon startLocation; private LatLon endLocation; - private Thread currentRunningJob; private String lastRouteCalcError; private String lastRouteCalcErrorShort; private long lastTimeEvaluatedRoute = 0; - private boolean waitingNextJob; private TransportRouteCalculationProgressCallback progressRoute; @@ -170,16 +177,16 @@ public class TransportRoutingHelper { this.currentRoute = currentRoute; } - public void addListener(IRouteInformationListener l){ + public void addListener(IRouteInformationListener l) { listeners.add(new WeakReference<>(l)); } - public boolean removeListener(IRouteInformationListener lt){ + public boolean removeListener(IRouteInformationListener lt) { Iterator> it = listeners.iterator(); - while(it.hasNext()) { + while (it.hasNext()) { WeakReference ref = it.next(); IRouteInformationListener l = ref.get(); - if(l == null || lt == l) { + if (l == null || lt == l) { it.remove(); return true; } @@ -212,18 +219,14 @@ public class TransportRoutingHelper { private void startRouteCalculationThread(TransportRouteCalculationParams params) { synchronized (this) { - final Thread prevRunningJob = currentRunningJob; app.getSettings().LAST_ROUTE_APPLICATION_MODE.set(routingHelper.getAppMode()); - RouteRecalculationThread newThread = - new RouteRecalculationThread("Calculating public transport route", params, - app.getSettings().SAFE_MODE.get() ? null : NativeOsmandLibrary.getLoadedLibrary()); - currentRunningJob = newThread; + RouteRecalculationTask newTask = new RouteRecalculationTask(this, params, + app.getSettings().SAFE_MODE.get() ? null : NativeOsmandLibrary.getLoadedLibrary()); + lastTask = newTask; startProgress(params); updateProgress(params); - if (prevRunningJob != null) { - newThread.setWaitPrevJob(prevRunningJob); - } - currentRunningJob.start(); + Future future = executor.submit(newTask); + tasksMap.put(future, newTask); } } @@ -250,10 +253,7 @@ public class TransportRoutingHelper { if (isRouteBeingCalculated()) { float pr = calculationProgress.getLinearProgress(); progressRoute.updateProgress((int) pr); - Thread t = currentRunningJob; - if (t instanceof RouteRecalculationThread && ((RouteRecalculationThread) t).params != params) { - // different calculation started - } else { + if (lastTask != null && lastTask.params == params) { updateProgress(params); } } else { @@ -268,7 +268,23 @@ public class TransportRoutingHelper { } public boolean isRouteBeingCalculated() { - return currentRunningJob instanceof RouteRecalculationThread || waitingNextJob; + synchronized (this) { + for (Future future : tasksMap.keySet()) { + if (!future.isDone()) { + return true; + } + } + } + return false; + } + + private void stopCalculation() { + synchronized (this) { + for (Map.Entry, RouteRecalculationTask> taskFuture : tasksMap.entrySet()) { + taskFuture.getValue().stopCalculation(); + taskFuture.getKey().cancel(false); + } + } } private void setNewRoute(final List res) { @@ -322,9 +338,7 @@ public class TransportRoutingHelper { } }); this.endLocation = newFinalLocation; - if (currentRunningJob instanceof RouteRecalculationThread) { - ((RouteRecalculationThread) currentRunningJob).stopCalculation(); - } + stopCalculation(); } private void setCurrentLocation(LatLon currentLocation) { @@ -335,15 +349,6 @@ public class TransportRoutingHelper { recalculateRouteInBackground(currentLocation, endLocation); } - private void showMessage(final String msg) { - app.runInUIThread(new Runnable() { - @Override - public void run() { - app.showToastMessage(msg); - } - }); - } - @Nullable public QuadRect getTransportRouteRect(@NonNull TransportRouteResult result) { TransportRoutingHelper transportRoutingHelper = app.getTransportRoutingHelper(); @@ -403,7 +408,7 @@ public class TransportRoutingHelper { } } - private class WalkingRouteSegment { + private static class WalkingRouteSegment { TransportRouteResultSegment s1; TransportRouteResultSegment s2; LatLon start; @@ -436,18 +441,24 @@ public class TransportRoutingHelper { } } - private class RouteRecalculationThread extends Thread { + private static class RouteRecalculationTask implements Runnable { + private final TransportRoutingHelper transportRoutingHelper; + private final RoutingHelper routingHelper; private final TransportRouteCalculationParams params; - private Thread prevRunningJob; private final Queue walkingSegmentsToCalculate = new ConcurrentLinkedQueue<>(); private Map, RouteCalculationResult> walkingRouteSegments = new HashMap<>(); private boolean walkingSegmentsCalculated; - private NativeLibrary lib; + private final NativeLibrary lib; - public RouteRecalculationThread(String name, TransportRouteCalculationParams params, NativeLibrary library) { - super(name); + String routeCalcError; + String routeCalcErrorShort; + + public RouteRecalculationTask(@NonNull TransportRoutingHelper transportRoutingHelper, + @NonNull TransportRouteCalculationParams params, @Nullable NativeLibrary library) { + this.transportRoutingHelper = transportRoutingHelper; + this.routingHelper = transportRoutingHelper.routingHelper; this.params = params; this.lib = library; if (params.calculationProgress == null) { @@ -459,9 +470,9 @@ public class TransportRoutingHelper { params.calculationProgress.isCancelled = true; } - /** * TODO Check if native lib available and calculate route there. + * * @param params * @return * @throws IOException @@ -473,18 +484,18 @@ public class TransportRoutingHelper { BinaryMapIndexReader[] files = params.ctx.getResourceManager().getTransportRoutingMapFiles(); params.params.clear(); OsmandSettings settings = params.ctx.getSettings(); - for(Map.Entry e : config.getRouter(params.mode.getRoutingProfile()).getParameters().entrySet()){ + for (Map.Entry e : config.getRouter(params.mode.getRoutingProfile()).getParameters().entrySet()) { String key = e.getKey(); GeneralRouter.RoutingParameter pr = e.getValue(); String vl; - if(pr.getType() == GeneralRouter.RoutingParameterType.BOOLEAN) { + if (pr.getType() == GeneralRouter.RoutingParameterType.BOOLEAN) { CommonPreference pref = settings.getCustomRoutingBooleanProperty(key, pr.getDefaultBoolean()); Boolean bool = pref.getModeValue(params.mode); vl = bool ? "true" : null; } else { vl = settings.getCustomRoutingProperty(key, "").getModeValue(params.mode); } - if(vl != null && vl.length() > 0) { + if (vl != null && vl.length() > 0) { params.params.put(key, vl); } } @@ -492,7 +503,7 @@ public class TransportRoutingHelper { TransportRoutingConfiguration cfg = new TransportRoutingConfiguration(prouter, params.params); TransportRoutingContext ctx = new TransportRoutingContext(cfg, library, files); - ctx.calculationProgress = params.calculationProgress; + ctx.calculationProgress = params.calculationProgress; if (ctx.library != null && !settings.PT_SAFE_MODE.get()) { NativeTransportRoutingResult[] nativeRes = library.runNativePTRouting( MapUtils.get31TileNumberX(params.start.getLongitude()), @@ -509,7 +520,6 @@ public class TransportRoutingHelper { @Nullable private RouteCalculationParams getWalkingRouteParams() { - ApplicationMode walkingMode = ApplicationMode.PEDESTRIAN; final WalkingRouteSegment walkingRouteSegment = walkingSegmentsToCalculate.poll(); @@ -517,13 +527,14 @@ public class TransportRoutingHelper { return null; } + OsmandApplication app = routingHelper.getApplication(); Location start = new Location(""); start.setLatitude(walkingRouteSegment.start.getLatitude()); start.setLongitude(walkingRouteSegment.start.getLongitude()); LatLon end = new LatLon(walkingRouteSegment.end.getLatitude(), walkingRouteSegment.end.getLongitude()); final float currentDistanceFromBegin = - RouteRecalculationThread.this.params.calculationProgress.distanceFromBegin + + RouteRecalculationTask.this.params.calculationProgress.distanceFromBegin + (walkingRouteSegment.s1 != null ? (float) walkingRouteSegment.s1.getTravelDist() : 0); final RouteCalculationParams params = new RouteCalculationParams(); @@ -547,8 +558,8 @@ public class TransportRoutingHelper { float p = Math.max(params.calculationProgress.distanceFromBegin, params.calculationProgress.distanceFromEnd); - RouteRecalculationThread.this.params.calculationProgress.distanceFromBegin = - Math.max(RouteRecalculationThread.this.params.calculationProgress.distanceFromBegin, currentDistanceFromBegin + p); + RouteRecalculationTask.this.params.calculationProgress.distanceFromBegin = + Math.max(RouteRecalculationTask.this.params.calculationProgress.distanceFromBegin, currentDistanceFromBegin + p); } @Override @@ -571,7 +582,7 @@ public class TransportRoutingHelper { params.resultListener = new RouteCalculationResultListener() { @Override public void onRouteCalculated(RouteCalculationResult route) { - RouteRecalculationThread.this.walkingRouteSegments.put(new Pair<>(walkingRouteSegment.s1, walkingRouteSegment.s2), route); + RouteRecalculationTask.this.walkingRouteSegments.put(new Pair<>(walkingRouteSegment.s1, walkingRouteSegment.s2), route); } }; @@ -619,26 +630,18 @@ public class TransportRoutingHelper { } } + private void showMessage(final String msg) { + final OsmandApplication app = routingHelper.getApplication(); + app.runInUIThread(new Runnable() { + @Override + public void run() { + app.showToastMessage(msg); + } + }); + } + @Override public void run() { - synchronized (TransportRoutingHelper.this) { - currentRunningJob = this; - waitingNextJob = prevRunningJob != null; - } - if (prevRunningJob != null) { - while (prevRunningJob.isAlive()) { - try { - Thread.sleep(50); - } catch (InterruptedException e) { - // ignore - } - } - synchronized (TransportRoutingHelper.this) { - currentRunningJob = this; - waitingNextJob = false; - } - } - List res = null; String error = null; try { @@ -651,38 +654,52 @@ public class TransportRoutingHelper { log.error(e); } if (params.calculationProgress.isCancelled) { - synchronized (TransportRoutingHelper.this) { - currentRunningJob = null; - } return; } - synchronized (TransportRoutingHelper.this) { - routes = res; - TransportRoutingHelper.this.walkingRouteSegments = walkingRouteSegments; + synchronized (transportRoutingHelper) { + transportRoutingHelper.routes = res; + transportRoutingHelper.walkingRouteSegments = walkingRouteSegments; if (res != null) { if (params.resultListener != null) { params.resultListener.onRouteCalculated(res); } } - currentRunningJob = null; } + OsmandApplication app = routingHelper.getApplication(); if (res != null) { - setNewRoute(res); + transportRoutingHelper.setNewRoute(res); } else if (error != null) { - lastRouteCalcError = app.getString(R.string.error_calculating_route) + ":\n" + error; - lastRouteCalcErrorShort = app.getString(R.string.error_calculating_route); - showMessage(lastRouteCalcError); + routeCalcError = app.getString(R.string.error_calculating_route) + ":\n" + error; + routeCalcErrorShort = app.getString(R.string.error_calculating_route); + showMessage(routeCalcError); } else { - lastRouteCalcError = app.getString(R.string.empty_route_calculated); - lastRouteCalcErrorShort = app.getString(R.string.empty_route_calculated); - showMessage(lastRouteCalcError); + routeCalcError = app.getString(R.string.empty_route_calculated); + routeCalcErrorShort = app.getString(R.string.empty_route_calculated); + showMessage(routeCalcError); } app.getNotificationHelper().refreshNotification(NAVIGATION); - lastTimeEvaluatedRoute = System.currentTimeMillis(); + } + } + + private class RouteRecalculationExecutor extends ThreadPoolExecutor { + + public RouteRecalculationExecutor() { + super(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); } - public void setWaitPrevJob(Thread prevRunningJob) { - this.prevRunningJob = prevRunningJob; + protected void afterExecute(Runnable r, Throwable t) { + super.afterExecute(r, t); + RouteRecalculationTask task = null; + synchronized (TransportRoutingHelper.this) { + if (r instanceof Future) { + task = tasksMap.remove(r); + } + } + if (t == null && task != null) { + lastRouteCalcError = task.routeCalcError; + lastRouteCalcErrorShort = task.routeCalcErrorShort; + } + lastTimeEvaluatedRoute = System.currentTimeMillis(); } } }