From 26e6c5f64efcea91f486fb73e9d069f013135ad3 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Mon, 5 Oct 2020 13:06:47 +0300 Subject: [PATCH 01/14] Passing isOutgoing. --- data/countries.txt | 2 +- generator/restriction_collector.cpp | 8 +- generator/routing_index_generator.cpp | 10 +- map/framework.cpp | 2 + routing/base/astar_algorithm.hpp | 321 +++++++++++++++++- routing/base/astar_graph.hpp | 2 +- routing/edge_estimator.cpp | 8 +- routing/edge_estimator.hpp | 2 +- routing/fake_ending.cpp | 8 +- routing/geometry.cpp | 15 +- routing/geometry.hpp | 15 +- routing/index_graph.cpp | 27 +- routing/index_graph.hpp | 8 +- routing/index_graph_loader.cpp | 30 +- routing/index_graph_starter.cpp | 42 +-- routing/index_graph_starter.hpp | 18 +- routing/index_graph_starter_joints.hpp | 59 +++- routing/index_router.cpp | 75 ++-- routing/junction_visitor.hpp | 4 +- routing/leaps_graph.cpp | 18 +- routing/leaps_graph.hpp | 4 +- routing/restriction_loader.cpp | 2 +- routing/routing_tests/index_graph_test.cpp | 2 +- routing/routing_tests/index_graph_tools.cpp | 4 +- routing/routing_tests/index_graph_tools.hpp | 8 +- routing/routing_tests/routing_algorithm.cpp | 4 +- routing/routing_tests/routing_algorithm.hpp | 2 +- routing/single_vehicle_world_graph.cpp | 36 +- routing/single_vehicle_world_graph.hpp | 16 +- routing/transit_graph.cpp | 4 +- routing/transit_graph.hpp | 2 +- routing/transit_world_graph.cpp | 36 +- routing/transit_world_graph.hpp | 10 +- routing/world_graph.cpp | 4 +- routing/world_graph.hpp | 14 +- track_analyzing/track_analyzer/cmd_tracks.cpp | 2 +- .../track_analyzer/crossroad_checker.cpp | 6 +- track_analyzing/track_matcher.cpp | 4 +- track_analyzing/utils.cpp | 4 +- 39 files changed, 608 insertions(+), 230 deletions(-) diff --git a/data/countries.txt b/data/countries.txt index 048435d51ec..e1b5e56026d 100644 --- a/data/countries.txt +++ b/data/countries.txt @@ -1,5 +1,5 @@ { - "v": 200607, + "v": 200920, "id": "Countries", "g": [ { diff --git a/generator/restriction_collector.cpp b/generator/restriction_collector.cpp index d02c02b4bae..3cc404fe3f0 100644 --- a/generator/restriction_collector.cpp +++ b/generator/restriction_collector.cpp @@ -129,8 +129,8 @@ bool RestrictionCollector::ParseRestrictions(std::string const & path) Joint::Id RestrictionCollector::GetFirstCommonJoint(uint32_t firstFeatureId, uint32_t secondFeatureId) const { - uint32_t const firstLen = m_indexGraph->GetGeometry().GetRoad(firstFeatureId).GetPointsCount(); - uint32_t const secondLen = m_indexGraph->GetGeometry().GetRoad(secondFeatureId).GetPointsCount(); + uint32_t const firstLen = m_indexGraph->GetGeometry().GetRoad(firstFeatureId, true /* isOutgoing */).GetPointsCount(); + uint32_t const secondLen = m_indexGraph->GetGeometry().GetRoad(secondFeatureId, true /* isOutgoing */).GetPointsCount(); auto const firstRoad = m_indexGraph->GetRoad(firstFeatureId); auto const secondRoad = m_indexGraph->GetRoad(secondFeatureId); @@ -155,7 +155,7 @@ bool RestrictionCollector::FeatureHasPointWithCoords(uint32_t featureId, m2::PointD const & coords) const { CHECK(m_indexGraph, ()); - auto const & roadGeometry = m_indexGraph->GetGeometry().GetRoad(featureId); + auto const & roadGeometry = m_indexGraph->GetGeometry().GetRoad(featureId, true /* isOutgoing */); uint32_t const pointsCount = roadGeometry.GetPointsCount(); for (uint32_t i = 0; i < pointsCount; ++i) { @@ -245,7 +245,7 @@ bool RestrictionCollector::CheckAndProcessUTurn(Restriction::Type & restrictionT uint32_t & featureId = featureIds.back(); - auto const & road = m_indexGraph->GetGeometry().GetRoad(featureId); + auto const & road = m_indexGraph->GetGeometry().GetRoad(featureId, true /* isOutgoing */); // Can not do UTurn from feature to the same feature if it is one way. if (road.IsOneWay()) return false; diff --git a/generator/routing_index_generator.cpp b/generator/routing_index_generator.cpp index ffd1b1e8696..31cd034e461 100644 --- a/generator/routing_index_generator.cpp +++ b/generator/routing_index_generator.cpp @@ -173,7 +173,7 @@ class IndexGraphWrapper final routing::Segment GetFinishSegment() const { return {}; } bool ConvertToReal(routing::Segment const & /* segment */) const { return false; } routing::RouteWeight HeuristicCostEstimate(routing::Segment const & /* from */, - ms::LatLon const & /* to */) + ms::LatLon const & /* to */, bool) { CHECK(false, ("This method exists only for compatibility with IndexGraphStarterJoints")); return routing::GetAStarWeightZero(); @@ -202,9 +202,9 @@ class IndexGraphWrapper final routing::RouteWeight GetAStarWeightEpsilon() { return routing::RouteWeight(0.0); } // @} - ms::LatLon const & GetPoint(routing::Segment const & s, bool forward) + ms::LatLon const & GetPoint(routing::Segment const & s, bool forward, bool isOutgoing) { - return m_graph.GetPoint(s, forward); + return m_graph.GetPoint(s, forward, isOutgoing); } void GetEdgesList(routing::Segment const & child, bool isOutgoing, @@ -234,7 +234,7 @@ class IndexGraphWrapper final } template - routing::RouteWeight HeuristicCostEstimate(Vertex const & /* from */, m2::PointD const & /* to */) + routing::RouteWeight HeuristicCostEstimate(Vertex const & /* from */, m2::PointD const & /* to */, bool) { CHECK(false, ("This method should not be use, it is just for compatibility with " "IndexGraphStarterJoints.")); @@ -256,7 +256,7 @@ class DijkstraWrapperJoints : public routing::IndexGraphStarterJoints(); } diff --git a/map/framework.cpp b/map/framework.cpp index 0306749e068..0c81866e137 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1481,6 +1481,7 @@ void Framework::MemoryWarning() void Framework::EnterBackground() { + LOG(LINFO, ("Framework::EnterBackground()")); m_startBackgroundTime = base::Timer::LocalTime(); settings::Set("LastEnterBackground", m_startBackgroundTime); @@ -1507,6 +1508,7 @@ void Framework::EnterBackground() void Framework::EnterForeground() { + LOG(LINFO, ("Framework::EnterForeground()")); m_startForegroundTime = base::Timer::LocalTime(); if (m_drapeEngine != nullptr && m_startBackgroundTime != 0.0) { diff --git a/routing/base/astar_algorithm.hpp b/routing/base/astar_algorithm.hpp index 1d774693e88..8515cbebf94 100644 --- a/routing/base/astar_algorithm.hpp +++ b/routing/base/astar_algorithm.hpp @@ -7,12 +7,16 @@ #include "base/assert.hpp" #include "base/cancellable.hpp" +#include "base/fifo_cache.hpp" #include "base/logging.hpp" #include +#include #include #include +#include #include +#include #include #include #include @@ -211,6 +215,8 @@ class AStarAlgorithm template Result FindPathBidirectional(P & params, RoutingResult & result) const; + template + Result FindPathBidirectionalOneThread(P & params, RoutingResult & result) const; // Adjust route to the previous one. // Expects |params.m_checkLengthCallback| to check wave propagation limit. @@ -267,12 +273,17 @@ class AStarAlgorithm { using Parents = typename Graph::Parents; - BidirectionalStepContext(bool forward, Vertex const & startVertex, Vertex const & finalVertex, - Graph & graph) - : forward(forward) - , startVertex(startVertex) - , finalVertex(finalVertex) - , graph(graph) + BidirectionalStepContext(std::mutex & mtx, std::mutex & mtxGr, bool forward, Vertex const & startVertex, + Vertex const & finalVertex, Graph & graph) + : mtx(mtx) + , mtxGr(mtxGr) + , forward(forward) + , startVertex(startVertex) + , finalVertex(finalVertex) + , graph(graph) +// , consistentHeuristics(300 /* capacity */, [this](Vertex const & v, Weight & w) { +// this->ConsistentHeuristicImpl(v, w); +// }) { bestVertex = forward ? startVertex : finalVertex; pS = ConsistentHeuristic(bestVertex); @@ -303,8 +314,11 @@ class AStarAlgorithm // particular routes when debugging turned out to be easier. Weight ConsistentHeuristic(Vertex const & v) const { - auto const piF = graph.HeuristicCostEstimate(v, finalVertex); - auto const piR = graph.HeuristicCostEstimate(v, startVertex); + Weight piF; + Weight piR; + piF = graph.HeuristicCostEstimate(v, finalVertex, forward); + piR = graph.HeuristicCostEstimate(v, startVertex, forward); + if (forward) { /// @todo careful: with this "return" here and below in the Backward case @@ -318,6 +332,28 @@ class AStarAlgorithm return 0.5 * (piR - piF); } } +// void ConsistentHeuristicImpl(Vertex const & v, Weight & weight) const +// { +// auto const piF = graph.HeuristicCostEstimate(v, finalVertex); +// auto const piR = graph.HeuristicCostEstimate(v, startVertex); +// if (forward) +// { +// /// @todo careful: with this "return" here and below in the Backward case +// /// the heuristic becomes inconsistent but still seems to work. +// /// return HeuristicCostEstimate(v, finalVertex); +// weight = 0.5 * (piF - piR); +// } +// else +// { +// // return HeuristicCostEstimate(v, startVertex); +// weight = 0.5 * (piR - piF); +// } +// } +// +// Weight ConsistentHeuristic(Vertex const & v) +// { +// return consistentHeuristics.GetValue(v); +// } bool ExistsStateWithBetterDistance(State const & state, Weight const & eps = Weight(0.0)) const { @@ -345,6 +381,8 @@ class AStarAlgorithm { auto const realDistance = state.distance + pS - state.heuristic; astar::VertexData const data(state.vertex, realDistance); + +// std::lock_guard lock(mtxGr); if (forward) graph.GetOutgoingEdgesList(data, adj); else @@ -353,6 +391,27 @@ class AStarAlgorithm Parents & GetParents() { return parent; } + bool ExistsStateWithBetterDistanceLock(State const & state, Weight const & eps = Weight(0.0)) + { + std::lock_guard lock(mtx); + return ExistsStateWithBetterDistance(state, eps); + } + + void UpdateDistanceLock(State const & state) + { + std::lock_guard lock(mtx); + UpdateDistance(state); + } + + std::optional GetDistanceLock(Vertex const & vertex) + { + std::lock_guard lock(mtx); + return GetDistance(vertex); + } + +// std::atomic fullProtection; + std::mutex & mtx; + std::mutex & mtxGr; bool const forward; Vertex const & startVertex; Vertex const & finalVertex; @@ -360,6 +419,7 @@ class AStarAlgorithm std::priority_queue, std::greater> queue; ska::bytell_hash_map bestDistance; +// FifoCache consistentHeuristics; Parents parent; Vertex bestVertex; @@ -482,8 +542,8 @@ AStarAlgorithm::FindPath(P & params, RoutingResult::FindPathBidirectional(P & params, auto const & finalVertex = params.m_finalVertex; auto const & startVertex = params.m_startVertex; - BidirectionalStepContext forward(true /* forward */, startVertex, finalVertex, graph); - BidirectionalStepContext backward(false /* forward */, startVertex, finalVertex, graph); + std::mutex mtx; + std::mutex mtxGr; + BidirectionalStepContext forward(mtx, mtxGr, true /* forward */, startVertex, finalVertex, graph); + BidirectionalStepContext backward(mtx, mtxGr, false /* forward */, startVertex, finalVertex, graph); + + auto & forwardParents = forward.GetParents(); + auto & backwardParents = backward.GetParents(); + + bool foundAnyPath = false; + auto bestPathReducedLength = kZeroDistance; + auto bestPathRealLength = kZeroDistance; + + forward.UpdateDistance(State(startVertex, kZeroDistance)); + forward.queue.push(State(startVertex, kZeroDistance, forward.ConsistentHeuristic(startVertex))); + + backward.UpdateDistance(State(finalVertex, kZeroDistance)); + backward.queue.push(State(finalVertex, kZeroDistance, backward.ConsistentHeuristic(finalVertex))); + + auto wave = [&epsilon](BidirectionalStepContext & context, std::atomic & queueIsEmpty, + BidirectionalStepContext & oppositeContext, std::atomic & oppositeQueueIsEmpty) + { + LOG(LINFO, ("------------------wave---------------------------", context.forward ? "forward" : "backward")); + size_t i = 0; + std::vector adj; + while (!context.queue.empty() /* && !oppositeQueueIsEmpty.load() */) + { + // TODO Take care exception top/pop problem. + State const stateV = context.queue.top(); + context.queue.pop(); + + if (context.ExistsStateWithBetterDistanceLock(stateV)) + continue; + +// params.m_onVisitedVertexCallback(stateV.vertex, context.forward ? context.finalVertex : context.startVertex); + // @TODO Think about concurrent access to graph. + context.GetAdjacencyList(stateV, adj); + auto const & pV = stateV.heuristic; + for (auto const & edge : adj) + { + State stateW(edge.GetTarget(), kZeroDistance); + + if (stateV.vertex == stateW.vertex) + continue; + + auto const weight = edge.GetWeight(); + auto const pW = context.ConsistentHeuristic(stateW.vertex); + auto const reducedWeight = weight + pW - pV; + + CHECK_GREATER_OR_EQUAL( + reducedWeight, -epsilon, + ("Invariant violated for:", "v =", stateV.vertex, "w =", stateW.vertex)); + + stateW.distance = stateV.distance + std::max(reducedWeight, kZeroDistance); + +// auto const fullLength = weight + stateV.distance + context.pS - pV; + +// if (!params.m_checkLengthCallback(fullLength)) +// continue; + + if (context.ExistsStateWithBetterDistanceLock(stateW, epsilon)) + continue; + + stateW.heuristic = pW; + context.UpdateDistanceLock(stateW); + context.UpdateParent(stateW.vertex, stateV.vertex); + ++i; + if (oppositeContext.GetDistanceLock(stateW.vertex)) // i == 896199 + { + LOG(LINFO, ("------------------wave end---------------------------", context.forward ? "forward" : "backward", stateW.vertex, i)); + return; // The waves are intersected. + } + + if (stateW.vertex != (context.forward ? context.finalVertex : context.startVertex)) + context.queue.push(stateW); + } + } + + if (context.queue.empty()) + queueIsEmpty.store(true); + LOG(LINFO, ("------------------wave end (empty)---------------------------", context.forward ? "forward" : "backward")); + }; + +// std::atomic foundAnyPathF; + std::atomic fwdIsEmpty; + std::atomic bwdIsEmpty; + + PeriodicPollCancellable periodicCancellable(params.m_cancellable); + + // Starting a thread. + { + base::ScopedTimerWithLog timer("Wave"); + auto backwardWave = std::async(std::launch::async, wave, std::ref(backward), + std::ref(bwdIsEmpty), std::ref(forward), std::ref(fwdIsEmpty)); + wave(forward, fwdIsEmpty, backward, bwdIsEmpty); + backwardWave.get(); + } + LOG(LINFO, ("---------------------------------------------")); + + // To use the search code both for backward and forward directions + // we keep the pointers to everything related to the search in the + // 'current' and 'next' directions. Swapping these pointers indicates + // changing the end we are searching from. + BidirectionalStepContext * cur = &forward; + BidirectionalStepContext * nxt = &backward; + + auto const getResult = [&]() { + if (!params.m_checkLengthCallback(bestPathRealLength)) + return Result::NoPath; + + ReconstructPathBidirectional(cur->bestVertex, nxt->bestVertex, cur->parent, nxt->parent, + result.m_path); + result.m_distance = bestPathRealLength; + CHECK(!result.m_path.empty(), ()); + if (!cur->forward) + reverse(result.m_path.begin(), result.m_path.end()); + + return Result::OK; + }; + + std::vector adj; + uint32_t steps = 0; + + // Waves have been intersected. The routing is finished in one thread. + while (!cur->queue.empty() && !nxt->queue.empty()) + { + ++steps; + + if (periodicCancellable.IsCancelled()) + return Result::Cancelled; + + if (steps % kQueueSwitchPeriod == 0) + std::swap(cur, nxt); + + if (foundAnyPath) + { + auto const curTop = cur->TopDistance(); + auto const nxtTop = nxt->TopDistance(); + + // The intuition behind this is that we cannot obtain a path shorter + // than the left side of the inequality because that is how any path we find + // will look like (see comment for curPathReducedLength below). + // We do not yet have the proof that we will not miss a good path by doing so. + + // The shortest reduced path corresponds to the shortest real path + // because the heuristic we use are consistent. + // It would be a mistake to make a decision based on real path lengths because + // several top states in a priority queue may have equal reduced path lengths and + // different real path lengths. + + if (curTop + nxtTop >= bestPathReducedLength - epsilon) + return getResult(); + } + + State const stateV = cur->queue.top(); + cur->queue.pop(); + + if (cur->ExistsStateWithBetterDistance(stateV)) + continue; + + params.m_onVisitedVertexCallback(stateV.vertex, + cur->forward ? cur->finalVertex : cur->startVertex); + + cur->GetAdjacencyList(stateV, adj); + auto const & pV = stateV.heuristic; + for (auto const & edge : adj) + { + State stateW(edge.GetTarget(), kZeroDistance); + + if (stateV.vertex == stateW.vertex) + continue; + + auto const weight = edge.GetWeight(); + auto const pW = cur->ConsistentHeuristic(stateW.vertex); + auto const reducedWeight = weight + pW - pV; + + CHECK_GREATER_OR_EQUAL(reducedWeight, -epsilon, + ("Invariant violated for:", "v =", stateV.vertex, "w =", stateW.vertex)); + + stateW.distance = stateV.distance + std::max(reducedWeight, kZeroDistance); + + auto const fullLength = weight + stateV.distance + cur->pS - pV; + if (!params.m_checkLengthCallback(fullLength)) + continue; + + if (cur->ExistsStateWithBetterDistance(stateW, epsilon)) + continue; + + stateW.heuristic = pW; + cur->UpdateDistance(stateW); + cur->UpdateParent(stateW.vertex, stateV.vertex); + + if (auto op = nxt->GetDistance(stateW.vertex); op) + { + auto const & distW = *op; + // Reduced length that the path we've just found has in the original graph: + // find the reduced length of the path's parts in the reduced forward and backward graphs. + auto const curPathReducedLength = stateW.distance + distW; + // No epsilon here: it is ok to overshoot slightly. + if ((!foundAnyPath || bestPathReducedLength > curPathReducedLength) && + graph.AreWavesConnectible(forwardParents, stateW.vertex, backwardParents)) + { + bestPathReducedLength = curPathReducedLength; + + bestPathRealLength = stateV.distance + weight + distW; + bestPathRealLength += cur->pS - pV; + bestPathRealLength += nxt->pS - nxt->ConsistentHeuristic(stateW.vertex); + + foundAnyPath = true; + cur->bestVertex = stateV.vertex; + nxt->bestVertex = stateW.vertex; + } + } + + if (stateW.vertex != (cur->forward ? cur->finalVertex : cur->startVertex)) + cur->queue.push(stateW); + } + } + + if (foundAnyPath) + return getResult(); + + return Result::NoPath; +} + +template +template +typename AStarAlgorithm::Result +AStarAlgorithm::FindPathBidirectionalOneThread(P & params, + RoutingResult & result) const +{ + auto const epsilon = params.m_weightEpsilon; + auto & graph = params.m_graph; + auto const & finalVertex = params.m_finalVertex; + auto const & startVertex = params.m_startVertex; + + std::mutex mtx; + BidirectionalStepContext forward(mtx, true /* forward */, startVertex, finalVertex, graph); + BidirectionalStepContext backward(mtx, false /* forward */, startVertex, finalVertex, graph); auto & forwardParents = forward.GetParents(); auto & backwardParents = backward.GetParents(); @@ -703,6 +999,7 @@ AStarAlgorithm::FindPathBidirectional(P & params, return Result::NoPath; } + template template typename AStarAlgorithm::Result diff --git a/routing/base/astar_graph.hpp b/routing/base/astar_graph.hpp index 37e95e34665..0e5f815b61d 100644 --- a/routing/base/astar_graph.hpp +++ b/routing/base/astar_graph.hpp @@ -20,7 +20,7 @@ class AStarGraph using Parents = ska::bytell_hash_map; - virtual Weight HeuristicCostEstimate(Vertex const & from, Vertex const & to) = 0; + virtual Weight HeuristicCostEstimate(Vertex const & from, Vertex const & to, bool isOutgoing) = 0; virtual void GetOutgoingEdgesList(astar::VertexData const & vertexData, std::vector & edges) = 0; diff --git a/routing/edge_estimator.cpp b/routing/edge_estimator.cpp index ca01b1be80d..e4f0cad3a0b 100644 --- a/routing/edge_estimator.cpp +++ b/routing/edge_estimator.cpp @@ -177,7 +177,7 @@ class PedestrianEstimator final : public EdgeEstimator } double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, - Purpose purpose) const override + Purpose purpose, bool isOutgoing) const override { return CalcClimbSegment(purpose, segment, road, GetPedestrianClimbPenalty); } @@ -206,7 +206,7 @@ class BicycleEstimator final : public EdgeEstimator } double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, - Purpose purpose) const override + Purpose purpose, bool isOutgoing) const override { return CalcClimbSegment(purpose, segment, road, GetBicycleClimbPenalty); } @@ -221,7 +221,7 @@ class CarEstimator final : public EdgeEstimator // EdgeEstimator overrides: double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, - Purpose purpose) const override; + Purpose purpose, bool isOutgoing) const override; double GetUTurnPenalty(Purpose /* purpose */) const override; double GetFerryLandingPenalty(Purpose purpose) const override; @@ -237,7 +237,7 @@ CarEstimator::CarEstimator(shared_ptr trafficStash, double maxWeig } double CarEstimator::CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, - Purpose purpose) const + Purpose purpose, bool isOutgoing) const { return CalcSegment(purpose, segment, road); } diff --git a/routing/edge_estimator.hpp b/routing/edge_estimator.hpp index 362a91ebe6e..7fe43bbe8ab 100644 --- a/routing/edge_estimator.hpp +++ b/routing/edge_estimator.hpp @@ -45,7 +45,7 @@ class EdgeEstimator double CalcOffroad(ms::LatLon const & from, ms::LatLon const & to, Purpose purpose) const; virtual double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, - Purpose purpose) const = 0; + Purpose purpose, bool isOutgoing) const = 0; virtual double GetUTurnPenalty(Purpose purpose) const = 0; virtual double GetFerryLandingPenalty(Purpose purpose) const = 0; diff --git a/routing/fake_ending.cpp b/routing/fake_ending.cpp index de96339a702..0559143f24b 100644 --- a/routing/fake_ending.cpp +++ b/routing/fake_ending.cpp @@ -61,9 +61,9 @@ FakeEnding MakeFakeEnding(vector const & segments, m2::PointD const & p { auto const & segment = segments[i]; - bool const oneWay = graph.IsOneWay(segment.GetMwmId(), segment.GetFeatureId()); - auto const & frontJunction = graph.GetJunction(segment, true /* front */); - auto const & backJunction = graph.GetJunction(segment, false /* front */); + bool const oneWay = graph.IsOneWay(segment.GetMwmId(), segment.GetFeatureId(), true); + auto const & frontJunction = graph.GetJunction(segment, true /* front */, true); + auto const & backJunction = graph.GetJunction(segment, false /* front */, true); auto const & projectedJunction = CalcProjectionToSegment(backJunction, frontJunction, point); ending.m_projections.emplace_back(segment, oneWay, frontJunction, backJunction, @@ -79,7 +79,7 @@ FakeEnding MakeFakeEnding(vector const & segments, m2::PointD const & p FakeEnding MakeFakeEnding(Segment const & segment, m2::PointD const & point, IndexGraph & graph) { - auto const & road = graph.GetGeometry().GetRoad(segment.GetFeatureId()); + auto const & road = graph.GetGeometry().GetRoad(segment.GetFeatureId(), true /* isOutgoing */); bool const oneWay = road.IsOneWay(); auto const & frontJunction = road.GetJunction(segment.GetPointId(true /* front */)); auto const & backJunction = road.GetJunction(segment.GetPointId(false /* front */)); diff --git a/routing/geometry.cpp b/routing/geometry.cpp index 0d7833c8a3e..8ce26f6c4c3 100644 --- a/routing/geometry.cpp +++ b/routing/geometry.cpp @@ -25,7 +25,7 @@ namespace { // @TODO(bykoianko) Consider setting cache size based on available memory. // Maximum road geometry cache size in items. -size_t constexpr kRoadsCacheSize = 5000; +size_t constexpr kRoadsCacheSize = 3500; double CalcFerryDurationHours(string const & durationHours, double roadLenKm) { @@ -257,17 +257,24 @@ Geometry::Geometry(unique_ptr loader) : m_loader(move(loader)) , m_featureIdToRoad(make_unique( kRoadsCacheSize, - [this](uint32_t featureId, RoadGeometry & road) { m_loader->Load(featureId, road); })) + [this](uint32_t featureId, RoadGeometry & road) { LoadGeomLock(featureId, road); })) + , m_featureIdToRoadBwd(make_unique( + kRoadsCacheSize, + [this](uint32_t featureId, RoadGeometry & road) { LoadGeomLock(featureId, road); })) { CHECK(m_loader, ()); } -RoadGeometry const & Geometry::GetRoad(uint32_t featureId) +RoadGeometry const & Geometry::GetRoad(uint32_t featureId, bool isOutgoing) { ASSERT(m_featureIdToRoad, ()); ASSERT(m_loader, ()); - return m_featureIdToRoad->GetValue(featureId); + std::lock_guard lock(m_loaderMtx); + if (isOutgoing) + return m_featureIdToRoad->GetValue(featureId); + + return m_featureIdToRoadBwd->GetValue(featureId); } // static diff --git a/routing/geometry.hpp b/routing/geometry.hpp index 1d60cc4f3c4..e9ee24384ba 100644 --- a/routing/geometry.hpp +++ b/routing/geometry.hpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -139,20 +140,28 @@ class Geometry final /// \note The reference returned by the method is valid until the next call of GetRoad() /// of GetPoint() methods. - RoadGeometry const & GetRoad(uint32_t featureId); + RoadGeometry const & GetRoad(uint32_t featureId, bool isOutgoing); /// \note The reference returned by the method is valid until the next call of GetRoad() /// of GetPoint() methods. - ms::LatLon const & GetPoint(RoadPoint const & rp) + ms::LatLon const & GetPoint(RoadPoint const & rp, bool isOutgoing) { - return GetRoad(rp.GetFeatureId()).GetPoint(rp.GetPointId()); + return GetRoad(rp.GetFeatureId(), isOutgoing).GetPoint(rp.GetPointId()); + } + + void LoadGeomLock(uint32_t featureId, RoadGeometry & road) + { + m_loader->Load(featureId, road); } private: using RoutingFifoCache = FifoCache>; + std::mutex m_loaderMtx; std::unique_ptr m_loader; +// std::unique_ptr m_loaderBwd; std::unique_ptr m_featureIdToRoad; + std::unique_ptr m_featureIdToRoadBwd; }; } // namespace routing diff --git a/routing/index_graph.cpp b/routing/index_graph.cpp index d168dbda3a8..07a78be8e08 100644 --- a/routing/index_graph.cpp +++ b/routing/index_graph.cpp @@ -59,7 +59,7 @@ bool IndexGraph::IsJointOrEnd(Segment const & segment, bool fromStart) if (pointId == 0) return true; - uint32_t const pointsNumber = GetGeometry().GetRoad(segment.GetFeatureId()).GetPointsCount(); + uint32_t const pointsNumber = GetGeometry().GetRoad(segment.GetFeatureId(), true /* isOutgoing */).GetPointsCount(); return pointId + 1 == pointsNumber; } @@ -112,7 +112,7 @@ void IndexGraph::GetLastPointsForJoint(vector const & children, for (auto const & child : children) { uint32_t const startPointId = child.GetPointId(!isOutgoing /* front */); - uint32_t const pointsNumber = m_geometry->GetRoad(child.GetFeatureId()).GetPointsCount(); + uint32_t const pointsNumber = m_geometry->GetRoad(child.GetFeatureId(), isOutgoing).GetPointsCount(); CHECK_LESS(startPointId, pointsNumber, ()); uint32_t endPointId; @@ -251,7 +251,7 @@ void IndexGraph::GetNeighboringEdges(astar::VertexData con vector & edges, Parents const & parents, bool useAccessConditional) { - RoadGeometry const & road = m_geometry->GetRoad(rp.GetFeatureId()); + RoadGeometry const & road = m_geometry->GetRoad(rp.GetFeatureId(), isOutgoing); if (!road.IsValid()) return; @@ -280,7 +280,7 @@ void IndexGraph::GetNeighboringEdges(astar::VertexData con void IndexGraph::GetSegmentCandidateForRoadPoint(RoadPoint const & rp, NumMwmId numMwmId, bool isOutgoing, std::vector & children) { - RoadGeometry const & road = m_geometry->GetRoad(rp.GetFeatureId()); + RoadGeometry const & road = m_geometry->GetRoad(rp.GetFeatureId(), isOutgoing); if (!road.IsValid()) return; @@ -446,9 +446,9 @@ void IndexGraph::GetNeighboringEdge(astar::VertexData cons edges.emplace_back(to, weight); } -IndexGraph::PenaltyData IndexGraph::GetRoadPenaltyData(Segment const & segment) +IndexGraph::PenaltyData IndexGraph::GetRoadPenaltyData(Segment const & segment, bool isOutgoing) { - auto const & road = m_geometry->GetRoad(segment.GetFeatureId()); + auto const & road = m_geometry->GetRoad(segment.GetFeatureId(), isOutgoing); PenaltyData result(road.IsPassThroughAllowed(), road.GetRoutingOptions().Has(RoutingOptions::Road::Ferry)); @@ -457,10 +457,11 @@ IndexGraph::PenaltyData IndexGraph::GetRoadPenaltyData(Segment const & segment) } RouteWeight IndexGraph::GetPenalties(EdgeEstimator::Purpose purpose, Segment const & u, - Segment const & v, optional const & prevWeight) + Segment const & v, optional const & prevWeight, + bool isOutgoing) { - auto const & fromPenaltyData = GetRoadPenaltyData(u); - auto const & toPenaltyData = GetRoadPenaltyData(v); + auto const & fromPenaltyData = GetRoadPenaltyData(u, isOutgoing); + auto const & toPenaltyData = GetRoadPenaltyData(v, isOutgoing); // Route crosses border of pass-through/non-pass-through area if |u| and |v| have different // pass through restrictions. int8_t const passThroughPenalty = @@ -536,7 +537,7 @@ bool IndexGraph::IsUTurnAndRestricted(Segment const & parent, Segment const & ch uint32_t const featureId = parent.GetFeatureId(); uint32_t const turnPoint = parent.GetPointId(isOutgoing); - auto const & roadGeometry = m_geometry->GetRoad(featureId); + auto const & roadGeometry = m_geometry->GetRoad(featureId, isOutgoing); RoadPoint const rp = parent.GetRoadPoint(isOutgoing); if (m_roadIndex.GetJointId(rp) == Joint::kInvalidId && !roadGeometry.IsEndPointId(turnPoint)) @@ -560,11 +561,11 @@ RouteWeight IndexGraph::CalculateEdgeWeight(EdgeEstimator::Purpose purpose, bool std::optional const & prevWeight) { auto const & segment = isOutgoing ? to : from; - auto const & road = m_geometry->GetRoad(segment.GetFeatureId()); + auto const & road = m_geometry->GetRoad(segment.GetFeatureId(), isOutgoing); - auto const weight = RouteWeight(m_estimator->CalcSegmentWeight(segment, road, purpose)); + auto const weight = RouteWeight(m_estimator->CalcSegmentWeight(segment, road, purpose, isOutgoing)); auto const & penalties = - GetPenalties(purpose, isOutgoing ? from : to, isOutgoing ? to : from, prevWeight); + GetPenalties(purpose, isOutgoing ? from : to, isOutgoing ? to : from, prevWeight, isOutgoing); return weight + penalties; } diff --git a/routing/index_graph.hpp b/routing/index_graph.hpp index 9c45e69cde5..6c66c74e057 100644 --- a/routing/index_graph.hpp +++ b/routing/index_graph.hpp @@ -113,9 +113,9 @@ class IndexGraph final std::vector & lastPoints); WorldGraphMode GetMode() const; - ms::LatLon const & GetPoint(Segment const & segment, bool front) + ms::LatLon const & GetPoint(Segment const & segment, bool front, bool isOutgoing) { - return GetGeometry().GetRoad(segment.GetFeatureId()).GetPoint(segment.GetPointId(front)); + return GetGeometry().GetRoad(segment.GetFeatureId(), isOutgoing).GetPoint(segment.GetPointId(front)); } /// \brief Check, that we can go to |currentFeatureId|. @@ -164,14 +164,14 @@ class IndexGraph final bool m_isFerry; }; - PenaltyData GetRoadPenaltyData(Segment const & segment); + PenaltyData GetRoadPenaltyData(Segment const & segment, bool isOutgoing); /// \brief Calculates penalties for moving from |u| to |v|. /// \param |prevWeight| uses for fetching access:conditional. In fact it is time when user /// will be at |u|. This time is based on start time of route building and weight of calculated /// path until |u|. RouteWeight GetPenalties(EdgeEstimator::Purpose purpose, Segment const & u, Segment const & v, - std::optional const & prevWeight); + std::optional const & prevWeight, bool isOutgoing); void GetSegmentCandidateForRoadPoint(RoadPoint const & rp, NumMwmId numMwmId, bool isOutgoing, std::vector & children); diff --git a/routing/index_graph_loader.cpp b/routing/index_graph_loader.cpp index 95adc4d4d6a..48c9f97f511 100644 --- a/routing/index_graph_loader.cpp +++ b/routing/index_graph_loader.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -54,11 +55,13 @@ class IndexGraphLoaderImpl final : public IndexGraphLoader VehicleType m_vehicleType; bool m_loadAltitudes; + std::mutex m_dataSourceMtx; DataSource & m_dataSource; shared_ptr m_numMwmIds; shared_ptr m_vehicleModelFactory; shared_ptr m_estimator; + std::mutex m_graphsMtx; unordered_map m_graphs; unordered_map>> m_cachedCameras; @@ -90,20 +93,26 @@ IndexGraphLoaderImpl::IndexGraphLoaderImpl( Geometry & IndexGraphLoaderImpl::GetGeometry(NumMwmId numMwmId) { - auto it = m_graphs.find(numMwmId); - if (it != m_graphs.end()) - return *it->second.m_geometry; + { + std::lock_guard guard(m_graphsMtx); + auto it = m_graphs.find(numMwmId); + if (it != m_graphs.end()) + return *it->second.m_geometry; + } return *CreateGeometry(numMwmId).m_geometry; } IndexGraph & IndexGraphLoaderImpl::GetIndexGraph(NumMwmId numMwmId) { - auto it = m_graphs.find(numMwmId); - if (it != m_graphs.end()) { - return it->second.m_indexGraph ? *it->second.m_indexGraph - : *CreateIndexGraph(numMwmId, it->second).m_indexGraph; + std::lock_guard guard(m_graphsMtx); + auto it = m_graphs.find(numMwmId); + if (it != m_graphs.end()) + { + return it->second.m_indexGraph ? *it->second.m_indexGraph + : *CreateIndexGraph(numMwmId, it->second).m_indexGraph; + } } return *CreateIndexGraph(numMwmId, CreateGeometry(numMwmId)).m_indexGraph; @@ -194,6 +203,7 @@ IndexGraphLoaderImpl::GraphAttrs & IndexGraphLoaderImpl::CreateGeometry(NumMwmId shared_ptr vehicleModel = m_vehicleModelFactory->GetVehicleModelForCountry(file.GetName()); + std::lock_guard guard(m_graphsMtx); auto & graph = m_graphs[numMwmId]; graph.m_geometry = make_shared(GeometryLoader::Create( m_dataSource, handle, vehicleModel, AttrLoader(m_dataSource, handle), m_loadAltitudes)); @@ -219,7 +229,11 @@ IndexGraphLoaderImpl::GraphAttrs & IndexGraphLoaderImpl::CreateIndexGraph( return graph; } -void IndexGraphLoaderImpl::Clear() { m_graphs.clear(); } +void IndexGraphLoaderImpl::Clear() +{ + std::lock_guard guard(m_graphsMtx); + m_graphs.clear(); +} bool ReadRoadAccessFromMwm(MwmValue const & mwmValue, VehicleType vehicleType, RoadAccess & roadAccess) diff --git a/routing/index_graph_starter.cpp b/routing/index_graph_starter.cpp index 4a9e07ae1ac..86d9445c57f 100644 --- a/routing/index_graph_starter.cpp +++ b/routing/index_graph_starter.cpp @@ -76,8 +76,8 @@ IndexGraphStarter::IndexGraphStarter(FakeEnding const & startEnding, m_otherEndings.push_back(startEnding); m_otherEndings.push_back(finishEnding); - auto const startPoint = GetPoint(GetStartSegment(), false /* front */); - auto const finishPoint = GetPoint(GetFinishSegment(), true /* front */); + auto const startPoint = GetPoint(GetStartSegment(), false /* front */, true /* isOutgoing */); + auto const finishPoint = GetPoint(GetFinishSegment(), true /* front */, true /* isOutgoing */); m_startToFinishDistanceM = ms::DistanceOnEarth(startPoint, finishPoint); } @@ -88,8 +88,8 @@ void IndexGraphStarter::Append(FakeEdgesContainer const & container) // It's important to calculate distance after m_fake.Append() because // we don't have finish segment in fake graph before m_fake.Append(). - auto const startPoint = GetPoint(GetStartSegment(), false /* front */); - auto const finishPoint = GetPoint(GetFinishSegment(), true /* front */); + auto const startPoint = GetPoint(GetStartSegment(), false /* front */, true /* isOutgoing */); + auto const finishPoint = GetPoint(GetFinishSegment(), true /* front */, true /* isOutgoing */); m_startToFinishDistanceM = ms::DistanceOnEarth(startPoint, finishPoint); m_fakeNumerationStart += container.m_fake.GetSize(); } @@ -122,7 +122,7 @@ LatLonWithAltitude const & IndexGraphStarter::GetJunction(Segment const & segmen return m_guides.GetJunction(segment, front); if (!IsFakeSegment(segment)) - return m_graph.GetJunction(segment, front); + return m_graph.GetJunction(segment, front, true); auto const & vertex = m_fake.GetVertex(segment); return front ? vertex.GetJunctionTo() : vertex.GetJunctionFrom(); @@ -140,26 +140,26 @@ LatLonWithAltitude const & IndexGraphStarter::GetRouteJunction( return GetJunction(segments[pointIndex], false); } -ms::LatLon const & IndexGraphStarter::GetPoint(Segment const & segment, bool front) const +ms::LatLon const & IndexGraphStarter::GetPoint(Segment const & segment, bool front, bool isOutgoing) const { return GetJunction(segment, front).GetLatLon(); } -bool IndexGraphStarter::IsRoutingOptionsGood(Segment const & segment) const +bool IndexGraphStarter::IsRoutingOptionsGood(Segment const & segment, bool isOutgoing) const { - return m_graph.IsRoutingOptionsGood(segment); + return m_graph.IsRoutingOptionsGood(segment, isOutgoing); } -RoutingOptions IndexGraphStarter::GetRoutingOptions(Segment const & segment) const +RoutingOptions IndexGraphStarter::GetRoutingOptions(Segment const & segment, bool isOutgoing) const { if (segment.IsRealSegment()) - return m_graph.GetRoutingOptions(segment); + return m_graph.GetRoutingOptions(segment, isOutgoing); Segment real; if (!m_fake.FindReal(segment, real)) return {}; - return m_graph.GetRoutingOptions(real); + return m_graph.GetRoutingOptions(real, isOutgoing); } set IndexGraphStarter::GetMwms() const @@ -206,7 +206,7 @@ void IndexGraphStarter::GetEdgesList(astar::VertexData const & v // Weight used only when isOutgoing = false for passing to m_guides and placing to |edges|. RouteWeight ingoingSegmentWeight; if (!isOutgoing) - ingoingSegmentWeight = CalcSegmentWeight(segment, EdgeEstimator::Purpose::Weight); + ingoingSegmentWeight = CalcSegmentWeight(segment, EdgeEstimator::Purpose::Weight, isOutgoing); if (IsFakeSegment(segment)) { @@ -232,7 +232,7 @@ void IndexGraphStarter::GetEdgesList(astar::VertexData const & v for (auto const & s : m_fake.GetEdges(segment, isOutgoing)) { - edges.emplace_back(s, isOutgoing ? CalcSegmentWeight(s, EdgeEstimator::Purpose::Weight) + edges.emplace_back(s, isOutgoing ? CalcSegmentWeight(s, EdgeEstimator::Purpose::Weight, isOutgoing) : ingoingSegmentWeight); } } @@ -260,13 +260,13 @@ RouteWeight IndexGraphStarter::CalcGuidesSegmentWeight(Segment const & segment, } RouteWeight IndexGraphStarter::CalcSegmentWeight(Segment const & segment, - EdgeEstimator::Purpose purpose) const + EdgeEstimator::Purpose purpose, bool isOutgoing) const { if (IsGuidesSegment(segment)) return CalcGuidesSegmentWeight(segment, purpose); if (!IsFakeSegment(segment)) - return m_graph.CalcSegmentWeight(segment, purpose); + return m_graph.CalcSegmentWeight(segment, purpose, isOutgoing); auto const & vertex = m_fake.GetVertex(segment); Segment real; @@ -274,7 +274,7 @@ RouteWeight IndexGraphStarter::CalcSegmentWeight(Segment const & segment, { auto const partLen = ms::DistanceOnEarth(vertex.GetPointFrom(), vertex.GetPointTo()); auto const fullLen = - ms::DistanceOnEarth(GetPoint(real, false /* front */), GetPoint(real, true /* front */)); + ms::DistanceOnEarth(GetPoint(real, false /* front */, isOutgoing), GetPoint(real, true /* front */, isOutgoing)); // Note 1. |fullLen| == 0.0 in case of Segment(s) with the same ends. // Note 2. There is the following logic behind |return 0.0 * m_graph.CalcSegmentWeight(real, ...);|: // it's necessary to return a instance of the structure |RouteWeight| with zero wight. @@ -282,7 +282,7 @@ RouteWeight IndexGraphStarter::CalcSegmentWeight(Segment const & segment, // may be kept in it and it is up to |RouteWeight| to know how to multiply by zero. Weight const weight = IsGuidesSegment(real) ? CalcGuidesSegmentWeight(real, purpose) - : m_graph.CalcSegmentWeight(real, purpose); + : m_graph.CalcSegmentWeight(real, purpose, isOutgoing); if (fullLen == 0.0) return 0.0 * weight; @@ -296,7 +296,7 @@ double IndexGraphStarter::CalculateETA(Segment const & from, Segment const & to) { // We don't distinguish fake segment weight and fake segment transit time. if (IsFakeSegment(to)) - return CalcSegmentWeight(to, EdgeEstimator::Purpose::ETA).GetWeight(); + return CalcSegmentWeight(to, EdgeEstimator::Purpose::ETA, true).GetWeight(); if (IsFakeSegment(from)) return CalculateETAWithoutPenalty(to); @@ -323,7 +323,7 @@ double IndexGraphStarter::CalculateETA(Segment const & from, Segment const & to) double IndexGraphStarter::CalculateETAWithoutPenalty(Segment const & segment) const { if (IsFakeSegment(segment)) - return CalcSegmentWeight(segment, EdgeEstimator::Purpose::ETA).GetWeight(); + return CalcSegmentWeight(segment, EdgeEstimator::Purpose::ETA, true).GetWeight(); if (IsGuidesSegment(segment)) return CalcGuidesSegmentWeight(segment, EdgeEstimator::Purpose::ETA).GetWeight(); @@ -545,7 +545,7 @@ void IndexGraphStarter::AddFakeEdges(Segment const & segment, bool isOutgoing, v { // For ingoing edges we use source weight which is the same for |s| and for |edge| and is // already calculated. - fakeEdges.emplace_back(s, isOutgoing ? CalcSegmentWeight(s, EdgeEstimator::Purpose::Weight) + fakeEdges.emplace_back(s, isOutgoing ? CalcSegmentWeight(s, EdgeEstimator::Purpose::Weight, isOutgoing) : edge.GetWeight()); } } @@ -586,6 +586,6 @@ RouteWeight IndexGraphStarter::GetAStarWeightEpsilon() // distinguish the point geometry changing in |kMwmPointAccuracy| radius of the same segments from // mwms with different versions. So let's use such epsilon to maintain the A* invariant. return kEps + - m_graph.HeuristicCostEstimate(ms::LatLon(0.0, 0.0), ms::LatLon(0.0, kMwmPointAccuracy)); + m_graph.HeuristicCostEstimate(ms::LatLon(0.0, 0.0), ms::LatLon(0.0, kMwmPointAccuracy), true); } } // namespace routing diff --git a/routing/index_graph_starter.hpp b/routing/index_graph_starter.hpp index 88172a558e7..11c8c74e77a 100644 --- a/routing/index_graph_starter.hpp +++ b/routing/index_graph_starter.hpp @@ -76,10 +76,10 @@ class IndexGraphStarter : public AStarGraph const & route, size_t pointIndex) const; - ms::LatLon const & GetPoint(Segment const & segment, bool front) const; + ms::LatLon const & GetPoint(Segment const & segment, bool front, bool isOutgoing) const; - bool IsRoutingOptionsGood(Segment const & segment) const; - RoutingOptions GetRoutingOptions(Segment const & segment) const; + bool IsRoutingOptionsGood(Segment const & segment, bool isOutgoing) const; + RoutingOptions GetRoutingOptions(Segment const & segment, bool isOutgoing) const; uint32_t GetNumFakeSegments() const { @@ -119,10 +119,10 @@ class IndexGraphStarter : public AStarGraph & parents) override @@ -149,12 +149,12 @@ class IndexGraphStarter : public AStarGraph #include #include +#include #include #include #include @@ -40,13 +41,13 @@ class IndexGraphStarterJoints : public AStarGraph const & vertexData, std::vector & edges) override @@ -184,6 +185,8 @@ class IndexGraphStarterJoints : public AStarGraph m_savedWeight; // JointSegment consists of two segments of one feature. @@ -209,8 +213,11 @@ class IndexGraphStarterJoints : public AStarGraph m_path; }; + std::mutex m_reconstructedFakeJointsMtx; std::map m_reconstructedFakeJoints; + // |m_startOutEdges| and |m_endOutEdges| are filled on initialization stage. + // So they may be used without any synchronization. // List of JointEdges that are outgoing from start. std::vector m_startOutEdges; // List of incoming to finish. @@ -259,7 +266,7 @@ void IndexGraphStarterJoints::InitEnding(Segment const & ending, bool sta segment = ending; auto & point = start ? m_startPoint : m_endPoint; - point = m_graph.GetPoint(ending, true /* front */); + point = m_graph.GetPoint(ending, true /* front */, true /* isOutgoing */); auto & endingJoint = start ? m_startJoint : m_endJoint; if (IsRealSegment(ending)) @@ -272,13 +279,17 @@ void IndexGraphStarterJoints::InitEnding(Segment const & ending, bool sta endingJoint = CreateFakeJoint(loopSegment, loopSegment); } - m_reconstructedFakeJoints[endingJoint] = ReconstructedPath({ending}, start); + { + std::lock_guard guard(m_reconstructedFakeJointsMtx); + m_reconstructedFakeJoints[endingJoint] = ReconstructedPath({ending}, start); + } auto & outEdges = start ? m_startOutEdges : m_endOutEdges; outEdges = FindFirstJoints(ending, start); if (!start) { + std::lock_guard guard(m_savedWeightMtx); m_savedWeight[m_endJoint] = Weight(0.0); for (auto const & edge : m_endOutEdges) m_savedWeight[edge.GetTarget()] = edge.GetWeight(); @@ -287,7 +298,7 @@ void IndexGraphStarterJoints::InitEnding(Segment const & ending, bool sta template RouteWeight IndexGraphStarterJoints::HeuristicCostEstimate(JointSegment const & from, - JointSegment const & to) + JointSegment const & to, bool isOutgoing) { ASSERT(to == m_startJoint || to == m_endJoint, ("Invariant violated.")); bool toEnd = to == m_endJoint; @@ -295,6 +306,7 @@ RouteWeight IndexGraphStarterJoints::HeuristicCostEstimate(JointSegment c Segment fromSegment; if (from.IsFake() || IsInvisible(from)) { + std::lock_guard guard(m_reconstructedFakeJointsMtx); ASSERT_NOT_EQUAL(m_reconstructedFakeJoints.count(from), 0, ()); fromSegment = m_reconstructedFakeJoints[from].m_path.back(); } @@ -303,18 +315,18 @@ RouteWeight IndexGraphStarterJoints::HeuristicCostEstimate(JointSegment c fromSegment = from.GetSegment(false /* start */); } - return toEnd ? m_graph.HeuristicCostEstimate(fromSegment, m_endPoint) - : m_graph.HeuristicCostEstimate(fromSegment, m_startPoint); + return toEnd ? m_graph.HeuristicCostEstimate(fromSegment, m_endPoint, isOutgoing) + : m_graph.HeuristicCostEstimate(fromSegment, m_startPoint, isOutgoing); } template ms::LatLon const & -IndexGraphStarterJoints::GetPoint(JointSegment const & jointSegment, bool start) +IndexGraphStarterJoints::GetPoint(JointSegment const & jointSegment, bool start, bool isOutgoing) { Segment segment = jointSegment.IsFake() ? m_fakeJointSegments[jointSegment].GetSegment(start) : jointSegment.GetSegment(start); - return m_graph.GetPoint(segment, jointSegment.IsForward()); + return m_graph.GetPoint(segment, jointSegment.IsForward(), isOutgoing); } template @@ -328,11 +340,15 @@ std::vector IndexGraphStarterJoints::ReconstructJoint(JointSegme // In case of a fake vertex we return its prebuilt path. if (joint.IsFake()) { - auto const it = m_reconstructedFakeJoints.find(joint); - CHECK(it != m_reconstructedFakeJoints.cend(), ("Can not find such fake joint")); + std::vector path; + { + std::lock_guard guard(m_reconstructedFakeJointsMtx); + auto const it = m_reconstructedFakeJoints.find(joint); + CHECK(it != m_reconstructedFakeJoints.cend(), ("Can not find such fake joint")); + path = it->second.m_path; + ASSERT(!path.empty(), ()); + } - auto path = it->second.m_path; - ASSERT(!path.empty(), ()); if (path.front() == m_startSegment && path.back() == m_endSegment) path.pop_back(); @@ -423,6 +439,7 @@ std::optional IndexGraphStarterJoints::GetParentSegment( } else { + std::lock_guard guard(m_savedWeightMtx); auto const it = m_savedWeight.find(vertex); CHECK(it != m_savedWeight.cend(), ("Can not find weight for:", vertex)); @@ -527,6 +544,7 @@ void IndexGraphStarterJoints::GetEdgeList( // |parentSegment| is parent-vertex from which we search children. // For correct weight calculation we should get weight of JointSegment, that // ends in |parentSegment| and add |parentWeight[i]| to the saved value. + std::lock_guard guard(m_savedWeightMtx); auto const it = m_savedWeight.find(vertex); CHECK(it != m_savedWeight.cend(), ("Can not find weight for:", vertex)); @@ -609,6 +627,7 @@ std::vector IndexGraphStarterJoints::FindFirstJoints(Segment c result.emplace_back(fakeJoint, weight[beforeConvert]); std::vector path = reconstructPath(beforeConvert, fromStart); + std::lock_guard guard(m_reconstructedFakeJointsMtx); m_reconstructedFakeJoints.emplace(fakeJoint, ReconstructedPath(std::move(path), fromStart)); }; @@ -618,10 +637,10 @@ std::vector IndexGraphStarterJoints::FindFirstJoints(Segment c CHECK(!IsRealSegment(fake), ()); bool const hasSameFront = - m_graph.GetPoint(fake, true /* front */) == m_graph.GetPoint(segment, true); + m_graph.GetPoint(fake, true /* front */, true /* isOutgoing */) == m_graph.GetPoint(segment, true, true /* isOutgoing */); bool const hasSameBack = - m_graph.GetPoint(fake, false /* front */) == m_graph.GetPoint(segment, false); + m_graph.GetPoint(fake, false /* front */, true /* isOutgoing */) == m_graph.GetPoint(segment, false, true /* isOutgoing */); return (fromStart && hasSameFront) || (!fromStart && hasSameBack); }; @@ -683,9 +702,15 @@ void IndexGraphStarterJoints::Reset() m_endJoint = JointSegment(); m_startSegment = Segment(); m_endSegment = Segment(); - m_savedWeight.clear(); + { + std::lock_guard guard(m_savedWeightMtx); + m_savedWeight.clear(); + } m_fakeJointSegments.clear(); - m_reconstructedFakeJoints.clear(); + { + std::lock_guard guard(m_reconstructedFakeJointsMtx); + m_reconstructedFakeJoints.clear(); + } m_startOutEdges.clear(); m_endOutEdges.clear(); m_fakeId = 0; diff --git a/routing/index_router.cpp b/routing/index_router.cpp index 90610f5c7a0..d60784d7b84 100644 --- a/routing/index_router.cpp +++ b/routing/index_router.cpp @@ -593,9 +593,13 @@ RouterResultCode IndexRouter::DoCalculateRoute(Checkpoints const & checkpoints, vector startSegments; bool startSegmentIsAlmostCodirectionalDirection = false; - bool const foundStart = - FindBestSegments(checkpoints.GetPointFrom(), startDirection, true /* isOutgoing */, *graph, - startSegments, startSegmentIsAlmostCodirectionalDirection); + bool foundStart = false; + { + base::ScopedTimerWithLog timer("MTR FindBestSegments"); + foundStart = + FindBestSegments(checkpoints.GetPointFrom(), startDirection, true /* isOutgoing */, *graph, + startSegments, startSegmentIsAlmostCodirectionalDirection); + } m_guides.SetGuidesGraphParams(guidesMwmId, m_estimator->GetMaxWeightSpeedMpS()); m_guides.ConnectToGuidesGraph(checkpoints.GetPoints()); @@ -629,15 +633,18 @@ RouterResultCode IndexRouter::DoCalculateRoute(Checkpoints const & checkpoints, vector finishSegments; bool dummy = false; - // Stop building route if |finishCheckpoint| is not connected to OSM and is not connected to - // the guides graph. - if (!FindBestSegments(finishCheckpoint, m2::PointD::Zero() /* direction */, - false /* isOutgoing */, *graph, finishSegments, - dummy /* bestSegmentIsAlmostCodirectional */) && - finishFakeEnding.m_projections.empty()) { - return isLastSubroute ? RouterResultCode::EndPointNotFound - : RouterResultCode::IntermediatePointNotFound; + base::ScopedTimerWithLog timer("MTR Find finish or intermediate segment."); + // Stop building route if |finishCheckpoint| is not connected to OSM and is not connected to + // the guides graph. + if (!FindBestSegments(finishCheckpoint, m2::PointD::Zero() /* direction */, + false /* isOutgoing */, *graph, finishSegments, + dummy /* bestSegmentIsAlmostCodirectional */) && + finishFakeEnding.m_projections.empty()) + { + return isLastSubroute ? RouterResultCode::EndPointNotFound + : RouterResultCode::IntermediatePointNotFound; + } } bool isStartSegmentStrictForward = (m_vehicleType == VehicleType::Car); @@ -710,7 +717,12 @@ RouterResultCode IndexRouter::DoCalculateRoute(Checkpoints const & checkpoints, // TODO (@gmoryes) https://jira.mail.ru/browse/MAPSME-10694 // We should do RedressRoute for each subroute separately. - auto redressResult = RedressRoute(segments, delegate.GetCancellable(), *starter, route); + RouterResultCode redressResult = RouterResultCode::InternalError; + + { + base::ScopedTimerWithLog timer("MTR RedressRoute."); + redressResult = RedressRoute(segments, delegate.GetCancellable(), *starter, route); + } if (redressResult != RouterResultCode::NoError) return redressResult; @@ -720,7 +732,7 @@ RouterResultCode IndexRouter::DoCalculateRoute(Checkpoints const & checkpoints, m_lastRoute = make_unique(checkpoints.GetStart(), checkpoints.GetFinish(), route.GetSubroutes()); for (Segment const & segment : segments) - m_lastRoute->AddStep(segment, mercator::FromLatLon(starter->GetPoint(segment, true /* front */))); + m_lastRoute->AddStep(segment, mercator::FromLatLon(starter->GetPoint(segment, true /* front */, true /* isOutgoing */))); m_lastFakeEdges = make_unique(move(*starter)); @@ -801,9 +813,13 @@ RouterResultCode IndexRouter::CalculateSubrouteJointsMode( nullptr /* prevRoute */, delegate.GetCancellable(), move(visitor), AStarLengthChecker(starter)); + RouterResultCode result = RouterResultCode::InternalError; RoutingResult routingResult; - RouterResultCode const result = - FindPath(params, {} /* mwmIds */, routingResult, WorldGraphMode::Joints); + { + base::ScopedTimerWithLog timer("MTR CalculateSubrouteJointsMode"); + result = FindPath( + params, {} /* mwmIds */, routingResult, WorldGraphMode::Joints); + } if (result != RouterResultCode::NoError) return result; @@ -863,9 +879,13 @@ RouterResultCode IndexRouter::CalculateSubrouteLeapsOnlyMode( nullptr /* prevRoute */, delegate.GetCancellable(), move(visitor), AStarLengthChecker(starter)); + RouterResultCode result; RoutingResult routingResult; - RouterResultCode const result = - FindPath(params, {} /* mwmIds */, routingResult, WorldGraphMode::LeapsOnly); + { + base::ScopedTimerWithLog timer("MTR Cross mwm FindPath."); + result = FindPath( + params, {} /* mwmIds */, routingResult, WorldGraphMode::LeapsOnly); + } progress->PushAndDropLastSubProgress(); @@ -924,7 +944,7 @@ RouterResultCode IndexRouter::AdjustRoute(Checkpoints const & checkpoints, { auto const & step = steps[i]; prevEdges.emplace_back(step.GetSegment(), starter.CalcSegmentWeight(step.GetSegment(), - EdgeEstimator::Purpose::Weight)); + EdgeEstimator::Purpose::Weight, true)); } using Visitor = JunctionVisitor; @@ -1333,8 +1353,8 @@ RouterResultCode IndexRouter::ProcessLeapsJoints(vector const & input, maxStart = max(maxStart, start); auto const contribCoef = static_cast(end - maxStart + 1) / (input.size()); - auto const startPoint = starter.GetPoint(input[start], true /* front */); - auto const endPoint = starter.GetPoint(input[end], true /* front */); + auto const startPoint = starter.GetPoint(input[start], true /* front */, true /* isOutgoing */); + auto const endPoint = starter.GetPoint(input[end], true /* front */, true /* isOutgoing */); progress->AppendSubProgress({startPoint, endPoint, contribCoef}); RouterResultCode resultCode = RouterResultCode::NoError; @@ -1353,7 +1373,10 @@ RouterResultCode IndexRouter::ProcessLeapsJoints(vector const & input, nullptr /* prevRoute */, delegate.GetCancellable(), move(visitor), AStarLengthChecker(starter)); - resultCode = FindPath(params, mwmIds, routingResult, mode); + { + base::ScopedTimerWithLog timer("MTR In one mwm after cross mwm."); + resultCode = FindPath(params, mwmIds, routingResult, mode); + } return resultCode; }; @@ -1381,8 +1404,8 @@ RouterResultCode IndexRouter::ProcessLeapsJoints(vector const & input, } LOG(LINFO, ("Can not find path", - "from:", starter.GetPoint(input[start], input[start].IsForward()), - "to:", starter.GetPoint(input[end], input[end].IsForward()))); + "from:", starter.GetPoint(input[start], input[start].IsForward(), true /* isOutgoing */), + "to:", starter.GetPoint(input[end], input[end].IsForward(), true /* isOutgoing */))); return false; }; @@ -1412,12 +1435,12 @@ RouterResultCode IndexRouter::ProcessLeapsJoints(vector const & input, if (!tryBuildRoute(prev, next, WorldGraphMode::JointSingleMwm, routingResult)) { - auto const prevPoint = starter.GetPoint(input[next], true); + auto const prevPoint = starter.GetPoint(input[next], true, true /* isOutgoing */); // |next + 1| - is the twin of |next| // |next + 2| - is the next exit. while (next + 2 < finishLeapStart && next != finishLeapStart) { - auto const point = starter.GetPoint(input[next + 2], true); + auto const point = starter.GetPoint(input[next + 2], true, true /* isOutgoing */); double const distBetweenExistsMeters = ms::DistanceOnEarth(point, prevPoint); static double constexpr kMinDistBetweenExitsM = 100000; // 100 km @@ -1513,7 +1536,7 @@ RouterResultCode IndexRouter::RedressRoute(vector const & segments, // to use them. if (m_vehicleType == VehicleType::Car) { - routeSegment.SetRoadTypes(starter.GetRoutingOptions(segment)); + routeSegment.SetRoadTypes(starter.GetRoutingOptions(segment, true /* isOutgoing */)); if (segment.IsRealSegment() && !AreSpeedCamerasProhibited(m_numMwmIds->GetFile(segment.GetMwmId()))) { diff --git a/routing/junction_visitor.hpp b/routing/junction_visitor.hpp index 9e09efcb443..9135fee6ab7 100644 --- a/routing/junction_visitor.hpp +++ b/routing/junction_visitor.hpp @@ -33,14 +33,14 @@ class JunctionVisitor if (m_visitCounter % m_visitPeriod != 0) return; - auto const & pointFrom = m_graph.GetPoint(from, true /* front */); + auto const & pointFrom = m_graph.GetPoint(from, true /* front */, true /* isOutgoing */); m_delegate.OnPointCheck(pointFrom); auto progress = m_progress.lock(); if (!progress) return; - auto const & pointTo = m_graph.GetPoint(to, true /* front */); + auto const & pointTo = m_graph.GetPoint(to, true /* front */, true /* isOutgoing */); auto const currentPercent = progress->UpdateProgress(pointFrom, pointTo); if (currentPercent - m_lastProgressPercent > kProgressInterval) { diff --git a/routing/leaps_graph.cpp b/routing/leaps_graph.cpp index 6a295865f52..9ed11a374b5 100644 --- a/routing/leaps_graph.cpp +++ b/routing/leaps_graph.cpp @@ -10,8 +10,8 @@ namespace routing LeapsGraph::LeapsGraph(IndexGraphStarter & starter, MwmHierarchyHandler && hierarchyHandler) : m_starter(starter), m_hierarchyHandler(std::move(hierarchyHandler)) { - m_startPoint = m_starter.GetPoint(m_starter.GetStartSegment(), true /* front */); - m_finishPoint = m_starter.GetPoint(m_starter.GetFinishSegment(), true /* front */); + m_startPoint = m_starter.GetPoint(m_starter.GetStartSegment(), true /* front */, true /* isOutgoing */); + m_finishPoint = m_starter.GetPoint(m_starter.GetFinishSegment(), true /* front */, true /* isOutgoing */); m_startSegment = m_starter.GetStartSegment(); m_finishSegment = m_starter.GetFinishSegment(); } @@ -28,12 +28,12 @@ void LeapsGraph::GetIngoingEdgesList(astar::VertexData const & v GetEdgesList(vertexData.m_vertex, false /* isOutgoing */, edges); } -RouteWeight LeapsGraph::HeuristicCostEstimate(Segment const & from, Segment const & to) +RouteWeight LeapsGraph::HeuristicCostEstimate(Segment const & from, Segment const & to, bool isOutgoing) { ASSERT(to == m_startSegment || to == m_finishSegment, ()); bool const toFinish = to == m_finishSegment; auto const & toPoint = toFinish ? m_finishPoint : m_startPoint; - return m_starter.HeuristicCostEstimate(from, toPoint); + return m_starter.HeuristicCostEstimate(from, toPoint, isOutgoing); } void LeapsGraph::GetEdgesList(Segment const & segment, bool isOutgoing, @@ -55,7 +55,7 @@ void LeapsGraph::GetEdgesList(Segment const & segment, bool isOutgoing, return GetEdgesListToFinish(segment, edges); } - if (!m_starter.IsRoutingOptionsGood(segment)) + if (!m_starter.IsRoutingOptionsGood(segment, isOutgoing)) return; auto & crossMwmGraph = m_starter.GetGraph().GetCrossMwmGraph(); @@ -86,7 +86,7 @@ void LeapsGraph::GetEdgesListFromStart(Segment const & segment, std::vector std::vector & edges) override; void GetIngoingEdgesList(astar::VertexData const & vertexData, std::vector & edges) override; - RouteWeight HeuristicCostEstimate(Segment const & from, Segment const & to) override; + RouteWeight HeuristicCostEstimate(Segment const & from, Segment const & to, bool isOutgoing) override; RouteWeight GetAStarWeightEpsilon() override; // @} Segment const & GetStartSegment() const; Segment const & GetFinishSegment() const; - ms::LatLon const & GetPoint(Segment const & segment, bool front) const; + ms::LatLon const & GetPoint(Segment const & segment, bool front, bool isOutgoing) const; private: void GetEdgesList(Segment const & segment, bool isOutgoing, std::vector & edges); diff --git a/routing/restriction_loader.cpp b/routing/restriction_loader.cpp index 24d51a17be0..19bc8eaa16f 100644 --- a/routing/restriction_loader.cpp +++ b/routing/restriction_loader.cpp @@ -162,7 +162,7 @@ void ConvertRestrictionsOnlyUTurnToNo(IndexGraph & graph, if (!graph.IsRoad(featureId)) continue; - uint32_t const n = graph.GetGeometry().GetRoad(featureId).GetPointsCount(); + uint32_t const n = graph.GetGeometry().GetRoad(featureId, true).GetPointsCount(); // !!! RoadJointIds const & joints = graph.GetRoad(uTurnRestriction.m_featureId); Joint::Id const joint = uTurnRestriction.m_viaIsFirstPoint ? joints.GetJointId(0) : joints.GetJointId(n - 1); diff --git a/routing/routing_tests/index_graph_test.cpp b/routing/routing_tests/index_graph_test.cpp index 759948b037b..79c6d6ae85a 100644 --- a/routing/routing_tests/index_graph_test.cpp +++ b/routing/routing_tests/index_graph_test.cpp @@ -81,7 +81,7 @@ void TestRoute(FakeEnding const & start, FakeEnding const & finish, size_t expec void TestEdges(IndexGraph & graph, Segment const & segment, vector const & expectedTargets, bool isOutgoing) { - ASSERT(segment.IsForward() || !graph.GetGeometry().GetRoad(segment.GetFeatureId()).IsOneWay(), + ASSERT(segment.IsForward() || !graph.GetGeometry().GetRoad(segment.GetFeatureId(), isOutgoing).IsOneWay(), ()); vector edges; diff --git a/routing/routing_tests/index_graph_tools.cpp b/routing/routing_tests/index_graph_tools.cpp index c25f645a31e..ff0227b238f 100644 --- a/routing/routing_tests/index_graph_tools.cpp +++ b/routing/routing_tests/index_graph_tools.cpp @@ -91,7 +91,7 @@ void NoUTurnRestrictionTest::TestRouteGeom(Segment const & start, Segment const for (size_t i = 0; i < routingResult.m_path.size(); ++i) { static auto constexpr kEps = 1e-3; - auto const point = m_graph->GetWorldGraph().GetPoint(routingResult.m_path[i], true /* forward */); + auto const point = m_graph->GetWorldGraph().GetPoint(routingResult.m_path[i], true /* forward */, true); if (!base::AlmostEqualAbs(mercator::FromLatLon(point), expectedRouteGeom[i], kEps)) { TEST(false, ("Coords missmated at index:", i, "expected:", expectedRouteGeom[i], @@ -137,7 +137,7 @@ void TestTransitGraphLoader::AddGraph(NumMwmId mwmId, unique_ptr g // WeightedEdgeEstimator -------------------------------------------------------------- double WeightedEdgeEstimator::CalcSegmentWeight(Segment const & segment, RoadGeometry const & /* road */, - EdgeEstimator::Purpose /* purpose */) const + EdgeEstimator::Purpose /* purpose */, bool isOutgoing) const { auto const it = m_segmentWeights.find(segment); CHECK(it != m_segmentWeights.cend(), ()); diff --git a/routing/routing_tests/index_graph_tools.hpp b/routing/routing_tests/index_graph_tools.hpp index adba903d74d..ce0d9d3c819 100644 --- a/routing/routing_tests/index_graph_tools.hpp +++ b/routing/routing_tests/index_graph_tools.hpp @@ -55,10 +55,10 @@ class WorldGraphForAStar : public AStarGraph // AStarGraph overrides: // @{ - Weight HeuristicCostEstimate(Vertex const & from, Vertex const & to) override + Weight HeuristicCostEstimate(Vertex const & from, Vertex const & to, bool isOutgoing) override { - return m_graph->HeuristicCostEstimate(m_graph->GetPoint(from, true /* front */), - m_graph->GetPoint(to, true /* front */)); + return m_graph->HeuristicCostEstimate(m_graph->GetPoint(from, true /* front */, isOutgoing), + m_graph->GetPoint(to, true /* front */, isOutgoing)); } void GetOutgoingEdgesList(astar::VertexData const & vertexData, @@ -177,7 +177,7 @@ class WeightedEdgeEstimator final : public EdgeEstimator ~WeightedEdgeEstimator() override = default; double CalcSegmentWeight(Segment const & segment, RoadGeometry const & /* road */, - EdgeEstimator::Purpose purpose) const override; + EdgeEstimator::Purpose purpose, bool isOutgoing) const override; double GetUTurnPenalty(Purpose purpose) const override; double GetFerryLandingPenalty(Purpose purpose) const override; diff --git a/routing/routing_tests/routing_algorithm.cpp b/routing/routing_tests/routing_algorithm.cpp index 5f023a6a3c6..d0bc28541f2 100644 --- a/routing/routing_tests/routing_algorithm.cpp +++ b/routing/routing_tests/routing_algorithm.cpp @@ -45,7 +45,7 @@ void UndirectedGraph::GetOutgoingEdgesList(astar::VertexData con GetEdgesList(vertexData.m_vertex, true /* isOutgoing */, adj); } -double UndirectedGraph::HeuristicCostEstimate(Vertex const & v, Vertex const & w) +double UndirectedGraph::HeuristicCostEstimate(Vertex const & v, Vertex const & w, bool) { return 0.0; } @@ -157,7 +157,7 @@ class RoadGraph : public Algorithm::Graph } } - double HeuristicCostEstimate(Vertex const & v, Vertex const & w) override + double HeuristicCostEstimate(Vertex const & v, Vertex const & w, bool) override { return TimeBetweenSec(v, w, m_maxSpeedMPS); } diff --git a/routing/routing_tests/routing_algorithm.hpp b/routing/routing_tests/routing_algorithm.hpp index 9057279e09b..50bd676681f 100644 --- a/routing/routing_tests/routing_algorithm.hpp +++ b/routing/routing_tests/routing_algorithm.hpp @@ -39,7 +39,7 @@ class UndirectedGraph : public AStarGraph std::vector & adj) override; void GetOutgoingEdgesList(astar::VertexData const & vertexData, std::vector & adj) override; - double HeuristicCostEstimate(Vertex const & v, Vertex const & w) override; + double HeuristicCostEstimate(Vertex const & v, Vertex const & w, bool) override; // @} void GetEdgesList(Vertex const & vertex, bool /* isOutgoing */, std::vector & adj); diff --git a/routing/single_vehicle_world_graph.cpp b/routing/single_vehicle_world_graph.cpp index eb40b9fccc5..1e683273f8e 100644 --- a/routing/single_vehicle_world_graph.cpp +++ b/routing/single_vehicle_world_graph.cpp @@ -125,39 +125,39 @@ void SingleVehicleWorldGraph::GetEdgeList( } LatLonWithAltitude const & SingleVehicleWorldGraph::GetJunction(Segment const & segment, - bool front) + bool front, bool isOutgoing) { - return GetRoadGeometry(segment.GetMwmId(), segment.GetFeatureId()) + return GetRoadGeometry(segment.GetMwmId(), segment.GetFeatureId(), isOutgoing) .GetJunction(segment.GetPointId(front)); } -ms::LatLon const & SingleVehicleWorldGraph::GetPoint(Segment const & segment, bool front) +ms::LatLon const & SingleVehicleWorldGraph::GetPoint(Segment const & segment, bool front, bool isOutgoing) { - return GetJunction(segment, front).GetLatLon(); + return GetJunction(segment, front, isOutgoing).GetLatLon(); } -bool SingleVehicleWorldGraph::IsOneWay(NumMwmId mwmId, uint32_t featureId) +bool SingleVehicleWorldGraph::IsOneWay(NumMwmId mwmId, uint32_t featureId, bool isOutgoing) { - return GetRoadGeometry(mwmId, featureId).IsOneWay(); + return GetRoadGeometry(mwmId, featureId, isOutgoing).IsOneWay(); } bool SingleVehicleWorldGraph::IsPassThroughAllowed(NumMwmId mwmId, uint32_t featureId) { - return GetRoadGeometry(mwmId, featureId).IsPassThroughAllowed(); + return GetRoadGeometry(mwmId, featureId, true).IsPassThroughAllowed(); /// !!! } RouteWeight SingleVehicleWorldGraph::HeuristicCostEstimate(ms::LatLon const & from, - ms::LatLon const & to) + ms::LatLon const & to, bool isOutgoing) { return RouteWeight(m_estimator->CalcHeuristic(from, to)); } RouteWeight SingleVehicleWorldGraph::CalcSegmentWeight(Segment const & segment, - EdgeEstimator::Purpose purpose) + EdgeEstimator::Purpose purpose, bool isOutgoing) { return RouteWeight(m_estimator->CalcSegmentWeight( - segment, GetRoadGeometry(segment.GetMwmId(), segment.GetFeatureId()), purpose)); + segment, GetRoadGeometry(segment.GetMwmId(), segment.GetFeatureId(), isOutgoing), purpose, isOutgoing)); } RouteWeight SingleVehicleWorldGraph::CalcLeapWeight(ms::LatLon const & from, @@ -185,8 +185,8 @@ double SingleVehicleWorldGraph::CalculateETA(Segment const & from, Segment const double SingleVehicleWorldGraph::CalculateETAWithoutPenalty(Segment const & segment) { return m_estimator->CalcSegmentWeight(segment, - GetRoadGeometry(segment.GetMwmId(), segment.GetFeatureId()), - EdgeEstimator::Purpose::ETA); + GetRoadGeometry(segment.GetMwmId(), segment.GetFeatureId(), true), + EdgeEstimator::Purpose::ETA, true); } vector const & SingleVehicleWorldGraph::GetTransitions(NumMwmId numMwmId, bool isEnter) @@ -202,9 +202,9 @@ vector SingleVehicleWorldGraph::GetSpeedCamInfo(Segme return m_loader->GetSpeedCameraInfo(segment); } -RoadGeometry const & SingleVehicleWorldGraph::GetRoadGeometry(NumMwmId mwmId, uint32_t featureId) +RoadGeometry const & SingleVehicleWorldGraph::GetRoadGeometry(NumMwmId mwmId, uint32_t featureId, bool isOutgoing) { - return m_loader->GetGeometry(mwmId).GetRoad(featureId); + return m_loader->GetGeometry(mwmId).GetRoad(featureId, isOutgoing); } void SingleVehicleWorldGraph::GetTwinsInner(Segment const & segment, bool isOutgoing, @@ -213,17 +213,17 @@ void SingleVehicleWorldGraph::GetTwinsInner(Segment const & segment, bool isOutg m_crossMwmGraph->GetTwins(segment, isOutgoing, twins); } -bool SingleVehicleWorldGraph::IsRoutingOptionsGood(Segment const & segment) +bool SingleVehicleWorldGraph::IsRoutingOptionsGood(Segment const & segment, bool isOutgoing) { - auto const & geometry = GetRoadGeometry(segment.GetMwmId(), segment.GetFeatureId()); + auto const & geometry = GetRoadGeometry(segment.GetMwmId(), segment.GetFeatureId(), isOutgoing); return geometry.SuitableForOptions(m_avoidRoutingOptions); } -RoutingOptions SingleVehicleWorldGraph::GetRoutingOptions(Segment const & segment) +RoutingOptions SingleVehicleWorldGraph::GetRoutingOptions(Segment const & segment, bool isOutgoing) { ASSERT(segment.IsRealSegment(), ()); - auto const & geometry = GetRoadGeometry(segment.GetMwmId(), segment.GetFeatureId()); + auto const & geometry = GetRoadGeometry(segment.GetMwmId(), segment.GetFeatureId(), isOutgoing); return geometry.GetRoutingOptions(); } diff --git a/routing/single_vehicle_world_graph.hpp b/routing/single_vehicle_world_graph.hpp index 2b4fad49ed1..d133a543354 100644 --- a/routing/single_vehicle_world_graph.hpp +++ b/routing/single_vehicle_world_graph.hpp @@ -50,19 +50,19 @@ class SingleVehicleWorldGraph final : public WorldGraph bool CheckLength(RouteWeight const &, double) const override { return true; } - LatLonWithAltitude const & GetJunction(Segment const & segment, bool front) override; - ms::LatLon const & GetPoint(Segment const & segment, bool front) override; + LatLonWithAltitude const & GetJunction(Segment const & segment, bool front, bool isOutgoing) override; + ms::LatLon const & GetPoint(Segment const & segment, bool front, bool isOutgoing) override; - bool IsOneWay(NumMwmId mwmId, uint32_t featureId) override; + bool IsOneWay(NumMwmId mwmId, uint32_t featureId, bool isOutgoing) override; bool IsPassThroughAllowed(NumMwmId mwmId, uint32_t featureId) override; void ClearCachedGraphs() override { m_loader->Clear(); } void SetMode(WorldGraphMode mode) override { m_mode = mode; } WorldGraphMode GetMode() const override { return m_mode; } - RouteWeight HeuristicCostEstimate(ms::LatLon const & from, ms::LatLon const & to) override; + RouteWeight HeuristicCostEstimate(ms::LatLon const & from, ms::LatLon const & to, bool isOutgoing) override; - RouteWeight CalcSegmentWeight(Segment const & segment, EdgeEstimator::Purpose purpose) override; + RouteWeight CalcSegmentWeight(Segment const & segment, EdgeEstimator::Purpose purpose, bool isOutgoing) override; RouteWeight CalcLeapWeight(ms::LatLon const & from, ms::LatLon const & to) const override; RouteWeight CalcOffroadWeight(ms::LatLon const & from, ms::LatLon const & to, EdgeEstimator::Purpose purpose) const override; @@ -73,8 +73,8 @@ class SingleVehicleWorldGraph final : public WorldGraph void SetRoutingOptions(RoutingOptions routingOptions) override { m_avoidRoutingOptions = routingOptions; } /// \returns true if feature, associated with segment satisfies users conditions. - bool IsRoutingOptionsGood(Segment const & segment) override; - RoutingOptions GetRoutingOptions(Segment const & segment) override; + bool IsRoutingOptionsGood(Segment const & segment, bool isOutgoing) override; + RoutingOptions GetRoutingOptions(Segment const & segment, bool isOutgoing) override; std::unique_ptr GetTransitInfo(Segment const & segment) override; std::vector GetSpeedCamInfo(Segment const & segment) override; @@ -124,7 +124,7 @@ class SingleVehicleWorldGraph final : public WorldGraph // WorldGraph overrides: void GetTwinsInner(Segment const & s, bool isOutgoing, std::vector & twins) override; - RoadGeometry const & GetRoadGeometry(NumMwmId mwmId, uint32_t featureId); + RoadGeometry const & GetRoadGeometry(NumMwmId mwmId, uint32_t featureId, bool isOutgoing); std::unique_ptr m_crossMwmGraph; std::unique_ptr m_loader; diff --git a/routing/transit_graph.cpp b/routing/transit_graph.cpp index 9da2a00b0b5..2d7226b5ecc 100644 --- a/routing/transit_graph.cpp +++ b/routing/transit_graph.cpp @@ -60,7 +60,7 @@ LatLonWithAltitude const & TransitGraph::GetJunction(Segment const & segment, } RouteWeight TransitGraph::CalcSegmentWeight(Segment const & segment, - EdgeEstimator::Purpose purpose) const + EdgeEstimator::Purpose purpose, bool isOutgoing) const { CHECK(IsTransitSegment(segment), ("Nontransit segment passed to TransitGraph.")); @@ -187,7 +187,7 @@ void TransitGraph::GetTransitEdges(Segment const & segment, bool isOutgoing, auto const & from = isOutgoing ? segment : s; auto const & to = isOutgoing ? s : segment; edges.emplace_back( - s, CalcSegmentWeight(to, EdgeEstimator::Purpose::Weight) + GetTransferPenalty(from, to)); + s, CalcSegmentWeight(to, EdgeEstimator::Purpose::Weight, isOutgoing) + GetTransferPenalty(from, to)); } } diff --git a/routing/transit_graph.hpp b/routing/transit_graph.hpp index 01ec75ea59a..7cdf6af81a5 100644 --- a/routing/transit_graph.hpp +++ b/routing/transit_graph.hpp @@ -43,7 +43,7 @@ class TransitGraph final ::transit::TransitVersion GetTransitVersion() const; LatLonWithAltitude const & GetJunction(Segment const & segment, bool front) const; - RouteWeight CalcSegmentWeight(Segment const & segment, EdgeEstimator::Purpose purpose) const; + RouteWeight CalcSegmentWeight(Segment const & segment, EdgeEstimator::Purpose purpose, bool isOutgoing) const; RouteWeight GetTransferPenalty(Segment const & from, Segment const & to) const; void GetTransitEdges(Segment const & segment, bool isOutgoing, std::vector & edges) const; diff --git a/routing/transit_world_graph.cpp b/routing/transit_world_graph.cpp index 4f54f1fa018..d9c3fb912cf 100644 --- a/routing/transit_world_graph.cpp +++ b/routing/transit_world_graph.cpp @@ -38,8 +38,8 @@ void TransitWorldGraph::GetEdgeList(astar::VertexData cons Segment real; if (transitGraph.FindReal(segment, real)) { - bool const haveSameFront = GetJunction(segment, true /* front */) == GetJunction(real, true); - bool const haveSameBack = GetJunction(segment, false /* front */) == GetJunction(real, false); + bool const haveSameFront = GetJunction(segment, true /* front */, isOutgoing) == GetJunction(real, true, isOutgoing); + bool const haveSameBack = GetJunction(segment, false /* front */, isOutgoing) == GetJunction(real, false, isOutgoing); if ((isOutgoing && haveSameFront) || (!isOutgoing && haveSameBack)) { astar::VertexData const data(real, vertexData.m_realDistance); @@ -60,8 +60,8 @@ void TransitWorldGraph::GetEdgeList(astar::VertexData cons auto const & edgeSegment = edge.GetTarget(); for (auto const & s : transitGraph.GetFake(edgeSegment)) { - bool const haveSameFront = GetJunction(edgeSegment, true /* front */) == GetJunction(s, true); - bool const haveSameBack = GetJunction(edgeSegment, false /* front */) == GetJunction(s, false); + bool const haveSameFront = GetJunction(edgeSegment, true /* front */, isOutgoing) == GetJunction(s, true, isOutgoing); + bool const haveSameBack = GetJunction(edgeSegment, false /* front */, isOutgoing) == GetJunction(s, false, isOutgoing); if ((isOutgoing && haveSameBack) || (!isOutgoing && haveSameFront)) fakeFromReal.emplace_back(s, edge.GetWeight()); } @@ -77,7 +77,7 @@ void TransitWorldGraph::GetEdgeList( CHECK(false, ("TransitWorldGraph does not support Joints mode.")); } -LatLonWithAltitude const & TransitWorldGraph::GetJunction(Segment const & segment, bool front) +LatLonWithAltitude const & TransitWorldGraph::GetJunction(Segment const & segment, bool front, bool isOutgoing) { if (TransitGraph::IsTransitSegment(segment)) return GetTransitGraph(segment.GetMwmId()).GetJunction(segment, front); @@ -86,12 +86,12 @@ LatLonWithAltitude const & TransitWorldGraph::GetJunction(Segment const & segmen .GetJunction(segment.GetPointId(front)); } -ms::LatLon const & TransitWorldGraph::GetPoint(Segment const & segment, bool front) +ms::LatLon const & TransitWorldGraph::GetPoint(Segment const & segment, bool front, bool isOutgoing) { - return GetJunction(segment, front).GetLatLon(); + return GetJunction(segment, front, isOutgoing).GetLatLon(); } -bool TransitWorldGraph::IsOneWay(NumMwmId mwmId, uint32_t featureId) +bool TransitWorldGraph::IsOneWay(NumMwmId mwmId, uint32_t featureId, bool isOutgoing) { if (TransitGraph::IsTransitFeature(featureId)) return true; @@ -111,22 +111,22 @@ void TransitWorldGraph::ClearCachedGraphs() m_transitLoader->Clear(); } -RouteWeight TransitWorldGraph::HeuristicCostEstimate(ms::LatLon const & from, ms::LatLon const & to) +RouteWeight TransitWorldGraph::HeuristicCostEstimate(ms::LatLon const & from, ms::LatLon const & to, bool isOutgoing) { return RouteWeight(m_estimator->CalcHeuristic(from, to)); } RouteWeight TransitWorldGraph::CalcSegmentWeight(Segment const & segment, - EdgeEstimator::Purpose purpose) + EdgeEstimator::Purpose purpose, bool isOutgoing) { if (TransitGraph::IsTransitSegment(segment)) { TransitGraph & transitGraph = GetTransitGraph(segment.GetMwmId()); - return transitGraph.CalcSegmentWeight(segment, purpose); + return transitGraph.CalcSegmentWeight(segment, purpose, isOutgoing); } return RouteWeight(m_estimator->CalcSegmentWeight( - segment, GetRealRoadGeometry(segment.GetMwmId(), segment.GetFeatureId()), purpose)); + segment, GetRealRoadGeometry(segment.GetMwmId(), segment.GetFeatureId()), purpose, isOutgoing)); } RouteWeight TransitWorldGraph::CalcLeapWeight(ms::LatLon const & from, ms::LatLon const & to) const @@ -144,15 +144,15 @@ RouteWeight TransitWorldGraph::CalcOffroadWeight(ms::LatLon const & from, double TransitWorldGraph::CalculateETA(Segment const & from, Segment const & to) { if (TransitGraph::IsTransitSegment(from)) - return CalcSegmentWeight(to, EdgeEstimator::Purpose::ETA).GetWeight(); + return CalcSegmentWeight(to, EdgeEstimator::Purpose::ETA, true).GetWeight(); if (TransitGraph::IsTransitSegment(to)) - return CalcSegmentWeight(to, EdgeEstimator::Purpose::ETA).GetWeight(); + return CalcSegmentWeight(to, EdgeEstimator::Purpose::ETA, true).GetWeight(); if (from.GetMwmId() != to.GetMwmId()) { return m_estimator->CalcSegmentWeight(to, GetRealRoadGeometry(to.GetMwmId(), to - .GetFeatureId()), EdgeEstimator::Purpose::ETA); + .GetFeatureId()), EdgeEstimator::Purpose::ETA, true); } auto & indexGraph = m_indexLoader->GetIndexGraph(from.GetMwmId()); @@ -164,11 +164,11 @@ double TransitWorldGraph::CalculateETA(Segment const & from, Segment const & to) double TransitWorldGraph::CalculateETAWithoutPenalty(Segment const & segment) { if (TransitGraph::IsTransitSegment(segment)) - return CalcSegmentWeight(segment, EdgeEstimator::Purpose::ETA).GetWeight(); + return CalcSegmentWeight(segment, EdgeEstimator::Purpose::ETA, true).GetWeight(); return m_estimator->CalcSegmentWeight( segment, GetRealRoadGeometry(segment.GetMwmId(), segment.GetFeatureId()), - EdgeEstimator::Purpose::ETA); + EdgeEstimator::Purpose::ETA, true); } unique_ptr TransitWorldGraph::GetTransitInfo(Segment const & segment) @@ -217,7 +217,7 @@ void TransitWorldGraph::GetTwinsInner(Segment const & segment, bool isOutgoing, RoadGeometry const & TransitWorldGraph::GetRealRoadGeometry(NumMwmId mwmId, uint32_t featureId) { CHECK(!TransitGraph::IsTransitFeature(featureId), ("GetRealRoadGeometry not designed for transit.")); - return m_indexLoader->GetGeometry(mwmId).GetRoad(featureId); + return m_indexLoader->GetGeometry(mwmId).GetRoad(featureId, true /* isOutgoing */); } void TransitWorldGraph::AddRealEdges(astar::VertexData const & vertexData, diff --git a/routing/transit_world_graph.hpp b/routing/transit_world_graph.hpp index fd7d1dd9824..1743e815840 100644 --- a/routing/transit_world_graph.hpp +++ b/routing/transit_world_graph.hpp @@ -51,19 +51,19 @@ class TransitWorldGraph final : public WorldGraph return weight.GetWeight() - weight.GetTransitTime() <= MaxPedestrianTimeSec(startToFinishDistanceM); } - LatLonWithAltitude const & GetJunction(Segment const & segment, bool front) override; - ms::LatLon const & GetPoint(Segment const & segment, bool front) override; + LatLonWithAltitude const & GetJunction(Segment const & segment, bool front, bool isOutgoing) override; + ms::LatLon const & GetPoint(Segment const & segment, bool front, bool isOutgoing) override; // All transit features are oneway. - bool IsOneWay(NumMwmId mwmId, uint32_t featureId) override; + bool IsOneWay(NumMwmId mwmId, uint32_t featureId, bool isOutgoing) override; // All transit features are allowed for through passage. bool IsPassThroughAllowed(NumMwmId mwmId, uint32_t featureId) override; void ClearCachedGraphs() override; void SetMode(WorldGraphMode mode) override { m_mode = mode; } WorldGraphMode GetMode() const override { return m_mode; } - RouteWeight HeuristicCostEstimate(ms::LatLon const & from, ms::LatLon const & to) override; + RouteWeight HeuristicCostEstimate(ms::LatLon const & from, ms::LatLon const & to, bool isOutgoing) override; - RouteWeight CalcSegmentWeight(Segment const & segment, EdgeEstimator::Purpose purpose) override; + RouteWeight CalcSegmentWeight(Segment const & segment, EdgeEstimator::Purpose purpose, bool isOutgoing) override; RouteWeight CalcLeapWeight(ms::LatLon const & from, ms::LatLon const & to) const override; RouteWeight CalcOffroadWeight(ms::LatLon const & from, ms::LatLon const & to, EdgeEstimator::Purpose purpose) const override; diff --git a/routing/world_graph.cpp b/routing/world_graph.cpp index 9bb48ec7131..b2954f1c004 100644 --- a/routing/world_graph.cpp +++ b/routing/world_graph.cpp @@ -28,12 +28,12 @@ void WorldGraph::GetTwins(Segment const & segment, bool isOutgoing, bool useRout SetMode(prevMode); } -RoutingOptions WorldGraph::GetRoutingOptions(Segment const & /* segment */) +RoutingOptions WorldGraph::GetRoutingOptions(Segment const & /* segment */, bool isOutgoing) { return {}; } -bool WorldGraph::IsRoutingOptionsGood(Segment const & /* segment */) +bool WorldGraph::IsRoutingOptionsGood(Segment const & /* segment */, bool isOutgoing) { return true; } diff --git a/routing/world_graph.hpp b/routing/world_graph.hpp index ed1f827efb0..6146df5dcab 100644 --- a/routing/world_graph.hpp +++ b/routing/world_graph.hpp @@ -65,9 +65,9 @@ class WorldGraph // start to finish of the route. virtual bool CheckLength(RouteWeight const & weight, double startToFinishDistanceM) const = 0; - virtual LatLonWithAltitude const & GetJunction(Segment const & segment, bool front) = 0; - virtual ms::LatLon const & GetPoint(Segment const & segment, bool front) = 0; - virtual bool IsOneWay(NumMwmId mwmId, uint32_t featureId) = 0; + virtual LatLonWithAltitude const & GetJunction(Segment const & segment, bool front, bool isOutgoing) = 0; + virtual ms::LatLon const & GetPoint(Segment const & segment, bool front, bool isOutgoing) = 0; + virtual bool IsOneWay(NumMwmId mwmId, uint32_t featureId, bool isOutgoing) = 0; // Checks whether feature is allowed for through passage. virtual bool IsPassThroughAllowed(NumMwmId mwmId, uint32_t featureId) = 0; @@ -77,10 +77,10 @@ class WorldGraph virtual void SetMode(WorldGraphMode mode) = 0; virtual WorldGraphMode GetMode() const = 0; - virtual RouteWeight HeuristicCostEstimate(ms::LatLon const & from, ms::LatLon const & to) = 0; + virtual RouteWeight HeuristicCostEstimate(ms::LatLon const & from, ms::LatLon const & to, bool isOutgoing) = 0; virtual RouteWeight CalcSegmentWeight(Segment const & segment, - EdgeEstimator::Purpose purpose) = 0; + EdgeEstimator::Purpose purpose, bool isOutgoin) = 0; virtual RouteWeight CalcLeapWeight(ms::LatLon const & from, ms::LatLon const & to) const = 0; @@ -93,8 +93,8 @@ class WorldGraph /// \returns transitions for mwm with id |numMwmId|. virtual std::vector const & GetTransitions(NumMwmId numMwmId, bool isEnter); - virtual bool IsRoutingOptionsGood(Segment const & /* segment */); - virtual RoutingOptions GetRoutingOptions(Segment const & /* segment */); + virtual bool IsRoutingOptionsGood(Segment const & /* segment */, bool isOutgoing); + virtual RoutingOptions GetRoutingOptions(Segment const & /* segment */, bool isOutgoing); virtual void SetRoutingOptions(RoutingOptions /* routingOptions */); virtual void SetAStarParents(bool forward, Parents & parents); diff --git a/track_analyzing/track_analyzer/cmd_tracks.cpp b/track_analyzing/track_analyzer/cmd_tracks.cpp index d06e9ce7db4..1f54e28dbfa 100644 --- a/track_analyzing/track_analyzer/cmd_tracks.cpp +++ b/track_analyzing/track_analyzer/cmd_tracks.cpp @@ -115,7 +115,7 @@ double EstimateDuration(MatchedTrack const & track, shared_ptr es continue; segment = point.GetSegment(); - result += estimator->CalcSegmentWeight(segment, geometry.GetRoad(segment.GetFeatureId()), + result += estimator->CalcSegmentWeight(segment, geometry.GetRoad(segment.GetFeatureId(), true /* isOutgoing */), EdgeEstimator::Purpose::ETA); } diff --git a/track_analyzing/track_analyzer/crossroad_checker.cpp b/track_analyzing/track_analyzer/crossroad_checker.cpp index 3aa17c7d5fe..a5e502117f7 100644 --- a/track_analyzing/track_analyzer/crossroad_checker.cpp +++ b/track_analyzing/track_analyzer/crossroad_checker.cpp @@ -78,9 +78,9 @@ namespace routing IsCrossroadChecker::Type IsCrossroadChecker::operator()(Segment const & current, Segment const & next) const { auto const currentSegmentFeatureId = current.GetFeatureId(); - auto const currentSegmentHwType = m_geometry.GetRoad(currentSegmentFeatureId).GetHighwayType(); + auto const currentSegmentHwType = m_geometry.GetRoad(currentSegmentFeatureId, true /* isOutgoing */).GetHighwayType(); auto const nextSegmentFeatureId = next.GetFeatureId(); - auto const nextSegmentHwType = m_geometry.GetRoad(nextSegmentFeatureId).GetHighwayType(); + auto const nextSegmentHwType = m_geometry.GetRoad(nextSegmentFeatureId, true /* isOutgoing */).GetHighwayType(); auto const currentRoadPoint = current.GetRoadPoint(true /* isFront */); auto const jointId = m_indexGraph.GetJointId(currentRoadPoint); if (jointId == Joint::kInvalidId) @@ -121,7 +121,7 @@ IsCrossroadChecker::Type IsCrossroadChecker::operator()(Segment const & current, if (pointFeatureId == currentSegmentFeatureId || pointFeatureId == nextSegmentFeatureId) return; - auto const & roadGeometry = m_geometry.GetRoad(pointFeatureId); + auto const & roadGeometry = m_geometry.GetRoad(pointFeatureId, true /* isOutgoing */); auto const pointHwType = roadGeometry.GetHighwayType(); if (currentSegmentHwType == pointHwType) return; diff --git a/track_analyzing/track_matcher.cpp b/track_analyzing/track_matcher.cpp index ef21b6dbd84..dbc457c9c18 100644 --- a/track_analyzing/track_matcher.cpp +++ b/track_analyzing/track_matcher.cpp @@ -35,8 +35,8 @@ double DistanceToSegment(m2::PointD const & segmentBegin, m2::PointD const & seg double DistanceToSegment(Segment const & segment, m2::PointD const & point, IndexGraph & indexGraph) { return DistanceToSegment( - mercator::FromLatLon(indexGraph.GetGeometry().GetPoint(segment.GetRoadPoint(false))), - mercator::FromLatLon(indexGraph.GetGeometry().GetPoint(segment.GetRoadPoint(true))), point); + mercator::FromLatLon(indexGraph.GetGeometry().GetPoint(segment.GetRoadPoint(false), true /* isOutgoing */)), + mercator::FromLatLon(indexGraph.GetGeometry().GetPoint(segment.GetRoadPoint(true), true /* isOutgoing */)), point); } bool EdgesContain(vector const & edges, Segment const & segment) diff --git a/track_analyzing/utils.cpp b/track_analyzing/utils.cpp index cb927731cf0..307e50dd0e9 100644 --- a/track_analyzing/utils.cpp +++ b/track_analyzing/utils.cpp @@ -31,8 +31,8 @@ double CalcSubtrackLength(MatchedTrack::const_iterator begin, MatchedTrack::cons { length += ms::DistanceOnEarth( - geometry.GetPoint(segment.GetRoadPoint(false /* front */)), - geometry.GetPoint(segment.GetRoadPoint(true /* front */))); + geometry.GetPoint(segment.GetRoadPoint(false /* front */), true /* isOutgoing */), + geometry.GetPoint(segment.GetRoadPoint(true /* front */), true /* isOutgoing */)); prevSegment = segment; } } From 3d188d5fcdf0dbf54f3418f37834a0f319a33815 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Mon, 5 Oct 2020 13:51:05 +0300 Subject: [PATCH 02/14] Fixing race condition. 12342, 10769, 10678. --- routing/index_graph_starter.cpp | 26 +++++++++++++++----------- routing/index_graph_starter.hpp | 7 ++++--- routing/index_road_graph.cpp | 8 ++++---- routing/index_router.cpp | 2 +- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/routing/index_graph_starter.cpp b/routing/index_graph_starter.cpp index 86d9445c57f..63ac498ce72 100644 --- a/routing/index_graph_starter.cpp +++ b/routing/index_graph_starter.cpp @@ -116,33 +116,35 @@ bool IndexGraphStarter::ConvertToReal(Segment & segment) const return m_fake.FindReal(Segment(segment), segment); } -LatLonWithAltitude const & IndexGraphStarter::GetJunction(Segment const & segment, bool front) const +LatLonWithAltitude const & IndexGraphStarter::GetJunction(Segment const & segment, bool front, + bool isOutgoing) const { if (IsGuidesSegment(segment)) return m_guides.GetJunction(segment, front); if (!IsFakeSegment(segment)) - return m_graph.GetJunction(segment, front, true); + return m_graph.GetJunction(segment, front, isOutgoing); auto const & vertex = m_fake.GetVertex(segment); return front ? vertex.GetJunctionTo() : vertex.GetJunctionFrom(); } -LatLonWithAltitude const & IndexGraphStarter::GetRouteJunction( - vector const & segments, size_t pointIndex) const +LatLonWithAltitude const & IndexGraphStarter::GetRouteJunction(vector const & segments, + size_t pointIndex, + bool isOutgoing) const { CHECK(!segments.empty(), ()); CHECK_LESS_OR_EQUAL( pointIndex, segments.size(), ("Point with index", pointIndex, "does not exist in route with size", segments.size())); if (pointIndex == segments.size()) - return GetJunction(segments[pointIndex - 1], true /* front */); - return GetJunction(segments[pointIndex], false); + return GetJunction(segments[pointIndex - 1], true /* front */, isOutgoing); + return GetJunction(segments[pointIndex], false, isOutgoing); } ms::LatLon const & IndexGraphStarter::GetPoint(Segment const & segment, bool front, bool isOutgoing) const { - return GetJunction(segment, front).GetLatLon(); + return GetJunction(segment, front, isOutgoing).GetLatLon(); } bool IndexGraphStarter::IsRoutingOptionsGood(Segment const & segment, bool isOutgoing) const @@ -213,8 +215,10 @@ void IndexGraphStarter::GetEdgesList(astar::VertexData const & v Segment real; if (m_fake.FindReal(segment, real)) { - bool const haveSameFront = GetJunction(segment, true /* front */) == GetJunction(real, true); - bool const haveSameBack = GetJunction(segment, false /* front */) == GetJunction(real, false); + bool const haveSameFront = + GetJunction(segment, true /* front */, isOutgoing) == GetJunction(real, true, isOutgoing); + bool const haveSameBack = + GetJunction(segment, false /* front */, isOutgoing) == GetJunction(real, false, isOutgoing); if ((isOutgoing && haveSameFront) || (!isOutgoing && haveSameBack)) { if (IsGuidesSegment(real)) @@ -534,12 +538,12 @@ void IndexGraphStarter::AddFakeEdges(Segment const & segment, bool isOutgoing, v // |segment| |s| // *------------>*-----------> bool const sIsOutgoing = - GetJunction(segment, true /* front */) == GetJunction(s, false /* front */); + GetJunction(segment, true /* front */, false) == GetJunction(s, false /* front */, false); // |s| |segment| // *------------>*-----------> bool const sIsIngoing = - GetJunction(s, true /* front */) == GetJunction(segment, false /* front */); + GetJunction(s, true /* front */, false) == GetJunction(segment, false /* front */, false); if ((isOutgoing && sIsOutgoing) || (!isOutgoing && sIsIngoing)) { diff --git a/routing/index_graph_starter.hpp b/routing/index_graph_starter.hpp index 11c8c74e77a..88851794b7b 100644 --- a/routing/index_graph_starter.hpp +++ b/routing/index_graph_starter.hpp @@ -73,9 +73,10 @@ class IndexGraphStarter : public AStarGraph const & route, - size_t pointIndex) const; + LatLonWithAltitude const & GetJunction(Segment const & segment, bool front, + bool isOutgoing) const; + LatLonWithAltitude const & GetRouteJunction(std::vector const & segments, size_t pointIndex, + bool isOutgoing) const; ms::LatLon const & GetPoint(Segment const & segment, bool front, bool isOutgoing) const; bool IsRoutingOptionsGood(Segment const & segment, bool isOutgoing) const; diff --git a/routing/index_road_graph.cpp b/routing/index_road_graph.cpp index b60a8083385..b2751f0d425 100644 --- a/routing/index_road_graph.cpp +++ b/routing/index_road_graph.cpp @@ -98,9 +98,9 @@ void IndexRoadGraph::GetRouteEdges(EdgeVector & edges) const for (Segment const & segment : m_segments) { auto const & junctionFrom = - m_starter.GetJunction(segment, false /* front */).ToPointWithAltitude(); + m_starter.GetJunction(segment, false /* front */, true /* isOutgoing */).ToPointWithAltitude(); auto const & junctionTo = - m_starter.GetJunction(segment, true /* front */).ToPointWithAltitude(); + m_starter.GetJunction(segment, true /* front */, true /* isOutgoing */).ToPointWithAltitude(); if (IndexGraphStarter::IsFakeSegment(segment) || TransitGraph::IsTransitSegment(segment)) { @@ -160,8 +160,8 @@ void IndexRoadGraph::GetEdges(geometry::PointWithAltitude const & junction, bool edges.push_back(Edge::MakeReal( FeatureID(mwmId, segment.GetFeatureId()), segment.IsForward(), segment.GetSegmentIdx(), - m_starter.GetJunction(segment, false /* front */).ToPointWithAltitude(), - m_starter.GetJunction(segment, true /* front */).ToPointWithAltitude())); + m_starter.GetJunction(segment, false /* front */, isOutgoing).ToPointWithAltitude(), + m_starter.GetJunction(segment, true /* front */, isOutgoing).ToPointWithAltitude())); } } diff --git a/routing/index_router.cpp b/routing/index_router.cpp index d60784d7b84..975e0492a67 100644 --- a/routing/index_router.cpp +++ b/routing/index_router.cpp @@ -1499,7 +1499,7 @@ RouterResultCode IndexRouter::RedressRoute(vector const & segments, junctions.reserve(numPoints); for (size_t i = 0; i < numPoints; ++i) - junctions.emplace_back(starter.GetRouteJunction(segments, i).ToPointWithAltitude()); + junctions.emplace_back(starter.GetRouteJunction(segments, i, true /* isOutgoing */).ToPointWithAltitude()); IndexRoadGraph roadGraph(m_numMwmIds, starter, segments, junctions, m_dataSource); starter.GetGraph().SetMode(WorldGraphMode::NoLeaps); From 9973b98d99bb2d6319403fb65854d74c6d0b58f9 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Tue, 6 Oct 2020 10:19:42 +0300 Subject: [PATCH 03/14] ios fixes. --- data/countries.txt | 2 +- routing/base/astar_algorithm.hpp | 8 ++++---- routing/index_router.hpp | 1 + routing/routing_tests/index_graph_tools.cpp | 8 ++++---- routing/routing_tests/index_graph_tools.hpp | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/data/countries.txt b/data/countries.txt index e1b5e56026d..0fe9c30ca21 100644 --- a/data/countries.txt +++ b/data/countries.txt @@ -1,5 +1,5 @@ { - "v": 200920, + "v": 200822, "id": "Countries", "g": [ { diff --git a/routing/base/astar_algorithm.hpp b/routing/base/astar_algorithm.hpp index 8515cbebf94..22103d9d9b1 100644 --- a/routing/base/astar_algorithm.hpp +++ b/routing/base/astar_algorithm.hpp @@ -638,7 +638,7 @@ AStarAlgorithm::FindPathBidirectional(P & params, auto wave = [&epsilon](BidirectionalStepContext & context, std::atomic & queueIsEmpty, BidirectionalStepContext & oppositeContext, std::atomic & oppositeQueueIsEmpty) { - LOG(LINFO, ("------------------wave---------------------------", context.forward ? "forward" : "backward")); + LOG(LINFO, ("---FindPath-------wave---------------------------", context.forward ? "forward" : "backward")); size_t i = 0; std::vector adj; while (!context.queue.empty() /* && !oppositeQueueIsEmpty.load() */) @@ -685,7 +685,7 @@ AStarAlgorithm::FindPathBidirectional(P & params, ++i; if (oppositeContext.GetDistanceLock(stateW.vertex)) // i == 896199 { - LOG(LINFO, ("------------------wave end---------------------------", context.forward ? "forward" : "backward", stateW.vertex, i)); + LOG(LINFO, ("---FindPath-------wave end---------------------------", context.forward ? "forward" : "backward", stateW.vertex, i)); return; // The waves are intersected. } @@ -696,7 +696,7 @@ AStarAlgorithm::FindPathBidirectional(P & params, if (context.queue.empty()) queueIsEmpty.store(true); - LOG(LINFO, ("------------------wave end (empty)---------------------------", context.forward ? "forward" : "backward")); + LOG(LINFO, ("----FindPath------wave end (empty)---------------------------", context.forward ? "forward" : "backward")); }; // std::atomic foundAnyPathF; @@ -713,7 +713,7 @@ AStarAlgorithm::FindPathBidirectional(P & params, wave(forward, fwdIsEmpty, backward, bwdIsEmpty); backwardWave.get(); } - LOG(LINFO, ("---------------------------------------------")); + LOG(LINFO, ("-------FindPath-------Finished-----------------")); // To use the search code both for backward and forward directions // we keep the pointers to everything related to the search in the diff --git a/routing/index_router.hpp b/routing/index_router.hpp index a4ac4c995e8..c31a7ed5642 100644 --- a/routing/index_router.hpp +++ b/routing/index_router.hpp @@ -211,6 +211,7 @@ class IndexRouter : public IRouter AStarParams & params, std::set const & mwmIds, RoutingResult & routingResult, WorldGraphMode mode) const { + base::ScopedTimerWithLog timerWithLog("***FindPath***", base::ScopedTimerWithLog::Measure::Seconds); AStarAlgorithm algorithm; return ConvertTransitResult( mwmIds, ConvertResult(algorithm.FindPathBidirectional(params, routingResult))); diff --git a/routing/routing_tests/index_graph_tools.cpp b/routing/routing_tests/index_graph_tools.cpp index ff0227b238f..a839ca365d8 100644 --- a/routing/routing_tests/index_graph_tools.cpp +++ b/routing/routing_tests/index_graph_tools.cpp @@ -518,13 +518,13 @@ void TestRouteGeometry(IndexGraphStarter & starter, for (auto const & routeSeg : routeSegs) { - auto const & ll = starter.GetPoint(routeSeg, false /* front */); + auto const & ll = starter.GetPoint(routeSeg, false /* front */, true); // Note. In case of A* router all internal points of route are duplicated. // So it's necessary to exclude the duplicates. pushPoint(ll); } - pushPoint(starter.GetPoint(routeSegs.back(), false /* front */)); + pushPoint(starter.GetPoint(routeSegs.back(), false /* front */, true)); TEST_EQUAL(geom.size(), expectedRouteGeom.size(), ("geom:", geom, "expectedRouteGeom:", expectedRouteGeom)); for (size_t i = 0; i < geom.size(); ++i) { @@ -582,8 +582,8 @@ void TestRestrictions(double expectedLength, double length = 0.0; for (auto const & segment : segments) { - auto const back = mercator::FromLatLon(starter.GetPoint(segment, false /* front */)); - auto const front = mercator::FromLatLon(starter.GetPoint(segment, true /* front */)); + auto const back = mercator::FromLatLon(starter.GetPoint(segment, false /* front */, true)); + auto const front = mercator::FromLatLon(starter.GetPoint(segment, true /* front */, true)); length += back.Length(front); } diff --git a/routing/routing_tests/index_graph_tools.hpp b/routing/routing_tests/index_graph_tools.hpp index ce0d9d3c819..6e8d9776480 100644 --- a/routing/routing_tests/index_graph_tools.hpp +++ b/routing/routing_tests/index_graph_tools.hpp @@ -58,7 +58,7 @@ class WorldGraphForAStar : public AStarGraph Weight HeuristicCostEstimate(Vertex const & from, Vertex const & to, bool isOutgoing) override { return m_graph->HeuristicCostEstimate(m_graph->GetPoint(from, true /* front */, isOutgoing), - m_graph->GetPoint(to, true /* front */, isOutgoing)); + m_graph->GetPoint(to, true /* front */, isOutgoing), isOutgoing); } void GetOutgoingEdgesList(astar::VertexData const & vertexData, From c291290c461fdb27af825d7d8f17b526fe5e1e53 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Thu, 8 Oct 2020 11:04:30 +0300 Subject: [PATCH 04/14] Map 200920 and moving mutex to LoadGeomLock(). --- data/countries.txt | 2 +- routing/geometry.cpp | 2 +- routing/geometry.hpp | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/data/countries.txt b/data/countries.txt index 0fe9c30ca21..e1b5e56026d 100644 --- a/data/countries.txt +++ b/data/countries.txt @@ -1,5 +1,5 @@ { - "v": 200822, + "v": 200920, "id": "Countries", "g": [ { diff --git a/routing/geometry.cpp b/routing/geometry.cpp index 8ce26f6c4c3..a3373143efc 100644 --- a/routing/geometry.cpp +++ b/routing/geometry.cpp @@ -270,7 +270,7 @@ RoadGeometry const & Geometry::GetRoad(uint32_t featureId, bool isOutgoing) ASSERT(m_featureIdToRoad, ()); ASSERT(m_loader, ()); - std::lock_guard lock(m_loaderMtx); +// std::lock_guard lock(m_loaderMtx); if (isOutgoing) return m_featureIdToRoad->GetValue(featureId); diff --git a/routing/geometry.hpp b/routing/geometry.hpp index e9ee24384ba..8d2d78ff006 100644 --- a/routing/geometry.hpp +++ b/routing/geometry.hpp @@ -151,6 +151,7 @@ class Geometry final void LoadGeomLock(uint32_t featureId, RoadGeometry & road) { + std::lock_guard lock(m_loaderMtx); m_loader->Load(featureId, road); } From 629d7bb57f723f0e70020bf0e468d44132bb3361 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Fri, 9 Oct 2020 18:52:54 +0300 Subject: [PATCH 05/14] Adding const correctness to method GetDistance(). --- routing/base/astar_algorithm.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routing/base/astar_algorithm.hpp b/routing/base/astar_algorithm.hpp index 22103d9d9b1..106cb0ce565 100644 --- a/routing/base/astar_algorithm.hpp +++ b/routing/base/astar_algorithm.hpp @@ -366,7 +366,7 @@ class AStarAlgorithm bestDistance.insert_or_assign(state.vertex, state.distance); } - std::optional GetDistance(Vertex const & vertex) + std::optional GetDistance(Vertex const & vertex) const { auto const it = bestDistance.find(vertex); return it != bestDistance.cend() ? std::optional(it->second) : std::nullopt; From aae34e856febef180978ddc2b1caaef09bee7b18 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Fri, 9 Oct 2020 20:13:30 +0300 Subject: [PATCH 06/14] Adding a graph for backward wave. And method SetupAlgorithmMode() should be const. --- routing/base/astar_algorithm.hpp | 9 +++++--- routing/index_router.cpp | 35 +++++++++++++++++++++----------- routing/index_router.hpp | 7 +++++-- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/routing/base/astar_algorithm.hpp b/routing/base/astar_algorithm.hpp index 106cb0ce565..b0deb3f8139 100644 --- a/routing/base/astar_algorithm.hpp +++ b/routing/base/astar_algorithm.hpp @@ -13,8 +13,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -80,11 +80,12 @@ class AStarAlgorithm typename LengthChecker = astar::DefaultLengthChecker> struct Params { - Params(Graph & graph, Vertex const & startVertex, Vertex const & finalVertex, + Params(Graph & graph, Graph & graphBwd, Vertex const & startVertex, Vertex const & finalVertex, std::vector const * prevRoute, base::Cancellable const & cancellable, Visitor && onVisitedVertexCallback = astar::DefaultVisitor(), LengthChecker && checkLengthCallback = astar::DefaultLengthChecker()) : m_graph(graph) + , m_graphBwd(graphBwd) , m_startVertex(startVertex) , m_finalVertex(finalVertex) , m_prevRoute(prevRoute) @@ -95,6 +96,7 @@ class AStarAlgorithm } Graph & m_graph; + Graph & m_graphBwd; Weight const m_weightEpsilon = m_graph.GetAStarWeightEpsilon(); Vertex const m_startVertex; // Used for FindPath, FindPathBidirectional. @@ -614,13 +616,14 @@ AStarAlgorithm::FindPathBidirectional(P & params, { auto const epsilon = params.m_weightEpsilon; auto & graph = params.m_graph; + auto & graphBwd = params.m_graphBwd; auto const & finalVertex = params.m_finalVertex; auto const & startVertex = params.m_startVertex; std::mutex mtx; std::mutex mtxGr; BidirectionalStepContext forward(mtx, mtxGr, true /* forward */, startVertex, finalVertex, graph); - BidirectionalStepContext backward(mtx, mtxGr, false /* forward */, startVertex, finalVertex, graph); + BidirectionalStepContext backward(mtx, mtxGr, false /* forward */, startVertex, finalVertex, graphBwd); auto & forwardParents = forward.GetParents(); auto & backwardParents = backward.GetParents(); diff --git a/routing/index_router.cpp b/routing/index_router.cpp index 975e0492a67..0a9f1435caf 100644 --- a/routing/index_router.cpp +++ b/routing/index_router.cpp @@ -663,6 +663,8 @@ RouterResultCode IndexRouter::DoCalculateRoute(Checkpoints const & checkpoints, starter ? starter->GetNumFakeSegments() + startIdx : startIdx; IndexGraphStarter subrouteStarter(startFakeEnding, finishFakeEnding, fakeNumerationStart, isStartSegmentStrictForward, *graph); + IndexGraphStarter subrouteStarterBwd(startFakeEnding, finishFakeEnding, fakeNumerationStart, + isStartSegmentStrictForward, *graph); if (m_guides.IsAttached()) { @@ -683,7 +685,7 @@ RouterResultCode IndexRouter::DoCalculateRoute(Checkpoints const & checkpoints, progress->AppendSubProgress(subProgress); SCOPE_GUARD(eraseProgress, [&progress]() { progress->PushAndDropLastSubProgress(); }); - auto const result = CalculateSubroute(checkpoints, i, delegate, progress, subrouteStarter, + auto const result = CalculateSubroute(checkpoints, i, delegate, progress, subrouteStarter, subrouteStarterBwd, subroute, m_guides.IsAttached()); if (result != RouterResultCode::NoError) @@ -769,6 +771,7 @@ RouterResultCode IndexRouter::CalculateSubroute(Checkpoints const & checkpoints, RouterDelegate const & delegate, shared_ptr const & progress, IndexGraphStarter & starter, + IndexGraphStarter & starterBwd, vector & subroute, bool guidesActive /* = false */) { @@ -776,6 +779,7 @@ RouterResultCode IndexRouter::CalculateSubroute(Checkpoints const & checkpoints, subroute.clear(); SetupAlgorithmMode(starter, guidesActive); + SetupAlgorithmMode(starterBwd, guidesActive); LOG(LINFO, ("Routing in mode:", starter.GetGraph().GetMode())); base::ScopedTimerWithLog timer("Route build"); @@ -783,11 +787,11 @@ RouterResultCode IndexRouter::CalculateSubroute(Checkpoints const & checkpoints, switch (mode) { case WorldGraphMode::Joints: - return CalculateSubrouteJointsMode(starter, delegate, progress, subroute); + return CalculateSubrouteJointsMode(starter, starterBwd, delegate, progress, subroute); case WorldGraphMode::NoLeaps: - return CalculateSubrouteNoLeapsMode(starter, delegate, progress, subroute); + return CalculateSubrouteNoLeapsMode(starter, starterBwd, delegate, progress, subroute); case WorldGraphMode::LeapsOnly: - return CalculateSubrouteLeapsOnlyMode(checkpoints, subrouteIdx, starter, delegate, progress, + return CalculateSubrouteLeapsOnlyMode(checkpoints, subrouteIdx, starter, starterBwd, delegate, progress, subroute); default: CHECK(false, ("Wrong WorldGraphMode here:", mode)); } @@ -795,11 +799,12 @@ RouterResultCode IndexRouter::CalculateSubroute(Checkpoints const & checkpoints, } RouterResultCode IndexRouter::CalculateSubrouteJointsMode( - IndexGraphStarter & starter, RouterDelegate const & delegate, + IndexGraphStarter & starter, IndexGraphStarter & starterBwd, RouterDelegate const & delegate, shared_ptr const & progress, vector & subroute) { using JointsStarter = IndexGraphStarterJoints; JointsStarter jointStarter(starter, starter.GetStartSegment(), starter.GetFinishSegment()); + JointsStarter jointStarterBwd(starterBwd, starterBwd.GetStartSegment(), starterBwd.GetFinishSegment()); using Visitor = JunctionVisitor; Visitor visitor(jointStarter, delegate, kVisitPeriod, progress); @@ -809,7 +814,7 @@ RouterResultCode IndexRouter::CalculateSubrouteJointsMode( using Weight = JointsStarter::Weight; AStarAlgorithm::Params params( - jointStarter, jointStarter.GetStartJoint(), jointStarter.GetFinishJoint(), + jointStarter, jointStarterBwd, jointStarter.GetStartJoint(), jointStarter.GetFinishJoint(), nullptr /* prevRoute */, delegate.GetCancellable(), move(visitor), AStarLengthChecker(starter)); @@ -829,7 +834,7 @@ RouterResultCode IndexRouter::CalculateSubrouteJointsMode( } RouterResultCode IndexRouter::CalculateSubrouteNoLeapsMode( - IndexGraphStarter & starter, RouterDelegate const & delegate, + IndexGraphStarter & starter, IndexGraphStarter & starterBwd, RouterDelegate const & delegate, shared_ptr const & progress, vector & subroute) { using Vertex = IndexGraphStarter::Vertex; @@ -840,7 +845,7 @@ RouterResultCode IndexRouter::CalculateSubrouteNoLeapsMode( Visitor visitor(starter, delegate, kVisitPeriod, progress); AStarAlgorithm::Params params( - starter, starter.GetStartSegment(), starter.GetFinishSegment(), nullptr /* prevRoute */, + starter, starterBwd, starter.GetStartSegment(), starter.GetFinishSegment(), nullptr /* prevRoute */, delegate.GetCancellable(), move(visitor), AStarLengthChecker(starter)); RoutingResult routingResult; @@ -857,10 +862,11 @@ RouterResultCode IndexRouter::CalculateSubrouteNoLeapsMode( RouterResultCode IndexRouter::CalculateSubrouteLeapsOnlyMode( Checkpoints const & checkpoints, size_t subrouteIdx, IndexGraphStarter & starter, - RouterDelegate const & delegate, shared_ptr const & progress, + IndexGraphStarter & starterBwd, RouterDelegate const & delegate, shared_ptr const & progress, vector & subroute) { LeapsGraph leapsGraph(starter, MwmHierarchyHandler(m_numMwmIds, m_countryParentNameGetterFn)); + LeapsGraph leapsGraphBwd(starterBwd, MwmHierarchyHandler(m_numMwmIds, m_countryParentNameGetterFn)); using Vertex = LeapsGraph::Vertex; using Edge = LeapsGraph::Edge; @@ -875,7 +881,7 @@ RouterResultCode IndexRouter::CalculateSubrouteLeapsOnlyMode( Visitor visitor(leapsGraph, delegate, kVisitPeriodForLeaps, progress); AStarAlgorithm::Params params( - leapsGraph, leapsGraph.GetStartSegment(), leapsGraph.GetFinishSegment(), + leapsGraph, leapsGraphBwd, leapsGraph.GetStartSegment(), leapsGraph.GetFinishSegment(), nullptr /* prevRoute */, delegate.GetCancellable(), move(visitor), AStarLengthChecker(starter)); @@ -955,8 +961,10 @@ RouterResultCode IndexRouter::AdjustRoute(Checkpoints const & checkpoints, using Weight = IndexGraphStarter::Weight; AStarAlgorithm algorithm; + // @TODO Duplicate starter. + CHECK(false, ("Duplicate stater.")); AStarAlgorithm::Params params( - starter, starter.GetStartSegment(), {} /* finalVertex */, &prevEdges, + starter, starter, starter.GetStartSegment(), {} /* finalVertex */, &prevEdges, delegate.GetCancellable(), move(visitor), AdjustLengthChecker(starter)); RoutingResult result; @@ -1368,8 +1376,10 @@ RouterResultCode IndexRouter::ProcessLeapsJoints(vector const & input, using Visitor = JunctionVisitor; Visitor visitor(jointStarter, delegate, kVisitPeriod, progress); + // @TODO Duplicate jointStarter. + CHECK(false, ("Duplicate jointStarter.")); AStarAlgorithm::Params params( - jointStarter, jointStarter.GetStartJoint(), jointStarter.GetFinishJoint(), + jointStarter, jointStarter, jointStarter.GetStartJoint(), jointStarter.GetFinishJoint(), nullptr /* prevRoute */, delegate.GetCancellable(), move(visitor), AStarLengthChecker(starter)); @@ -1633,6 +1643,7 @@ void IndexRouter::FillSpeedCamProhibitedMwms(vector const & segments, } } +// @TODO This method should be const. void IndexRouter::SetupAlgorithmMode(IndexGraphStarter & starter, bool guidesActive) { // We use NoLeaps for pedestrians and bicycles with route points near to the Guides tracks diff --git a/routing/index_router.hpp b/routing/index_router.hpp index c31a7ed5642..415cea6bdbd 100644 --- a/routing/index_router.hpp +++ b/routing/index_router.hpp @@ -102,15 +102,17 @@ class IndexRouter : public IRouter private: RouterResultCode CalculateSubrouteJointsMode(IndexGraphStarter & starter, + IndexGraphStarter & starterBwd, RouterDelegate const & delegate, std::shared_ptr const & progress, std::vector & subroute); - RouterResultCode CalculateSubrouteNoLeapsMode(IndexGraphStarter & starter, + RouterResultCode CalculateSubrouteNoLeapsMode(IndexGraphStarter & starter, IndexGraphStarter & starterBwd, RouterDelegate const & delegate, std::shared_ptr const & progress, std::vector & subroute); RouterResultCode CalculateSubrouteLeapsOnlyMode(Checkpoints const & checkpoints, size_t subrouteIdx, IndexGraphStarter & starter, + IndexGraphStarter & starterBwd, RouterDelegate const & delegate, std::shared_ptr const & progress, std::vector & subroute); @@ -121,7 +123,8 @@ class IndexRouter : public IRouter RouterResultCode CalculateSubroute(Checkpoints const & checkpoints, size_t subrouteIdx, RouterDelegate const & delegate, std::shared_ptr const & progress, - IndexGraphStarter & graph, std::vector & subroute, + IndexGraphStarter & graph, IndexGraphStarter & graphBwd, + std::vector & subroute, bool guidesActive = false); RouterResultCode AdjustRoute(Checkpoints const & checkpoints, From a131901b766481dc594b880d512f5e320392da8e Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Sun, 11 Oct 2020 07:28:59 +0300 Subject: [PATCH 07/14] Commenting altitude and geometry loader mutex. --- routing/base/astar_algorithm.hpp | 2 ++ routing/geometry.cpp | 6 +++--- routing/geometry.hpp | 4 ++-- routing/routing_tests/routing_algorithm.cpp | 3 ++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/routing/base/astar_algorithm.hpp b/routing/base/astar_algorithm.hpp index b0deb3f8139..6e1afc78b99 100644 --- a/routing/base/astar_algorithm.hpp +++ b/routing/base/astar_algorithm.hpp @@ -116,6 +116,7 @@ class AStarAlgorithm std::vector const * prevRoute, LengthChecker && checkLengthCallback = astar::DefaultLengthChecker()) : m_graph(graph) + , m_graphBwd(graph) , m_startVertex(startVertex) , m_finalVertex(finalVertex) , m_prevRoute(prevRoute) @@ -124,6 +125,7 @@ class AStarAlgorithm } Graph & m_graph; + Graph & m_graphBwd; Weight const m_weightEpsilon = m_graph.GetAStarWeightEpsilon(); Vertex const m_startVertex; // Used for FindPath, FindPathBidirectional. diff --git a/routing/geometry.cpp b/routing/geometry.cpp index a3373143efc..65f80f94e81 100644 --- a/routing/geometry.cpp +++ b/routing/geometry.cpp @@ -101,12 +101,12 @@ void GeometryLoaderImpl::Load(uint32_t featureId, RoadGeometry & road) feature->ParseGeometry(FeatureType::BEST_GEOMETRY); geometry::Altitudes const * altitudes = nullptr; - if (m_loadAltitudes) - altitudes = &(m_altitudeLoader.GetAltitudes(featureId, feature->GetPointsCount())); +// if (m_loadAltitudes) +// altitudes = &(m_altitudeLoader.GetAltitudes(featureId, feature->GetPointsCount())); road.Load(*m_vehicleModel, *feature, altitudes, m_attrLoader.m_cityRoads->IsCityRoad(featureId), m_attrLoader.m_maxspeeds->GetMaxspeed(featureId)); - m_altitudeLoader.ClearCache(); +// m_altitudeLoader.ClearCache(); } // FileGeometryLoader ------------------------------------------------------------------------------ diff --git a/routing/geometry.hpp b/routing/geometry.hpp index 8d2d78ff006..cff34518768 100644 --- a/routing/geometry.hpp +++ b/routing/geometry.hpp @@ -151,7 +151,7 @@ class Geometry final void LoadGeomLock(uint32_t featureId, RoadGeometry & road) { - std::lock_guard lock(m_loaderMtx); +// std::lock_guard lock(m_loaderMtx); m_loader->Load(featureId, road); } @@ -159,7 +159,7 @@ class Geometry final using RoutingFifoCache = FifoCache>; - std::mutex m_loaderMtx; +// std::mutex m_loaderMtx; std::unique_ptr m_loader; // std::unique_ptr m_loaderBwd; std::unique_ptr m_featureIdToRoad; diff --git a/routing/routing_tests/routing_algorithm.cpp b/routing/routing_tests/routing_algorithm.cpp index d0bc28541f2..e63e009dd97 100644 --- a/routing/routing_tests/routing_algorithm.cpp +++ b/routing/routing_tests/routing_algorithm.cpp @@ -205,7 +205,8 @@ TestAStarBidirectionalAlgo::Result TestAStarBidirectionalAlgo::CalculateRoute( { RoadGraph roadGraph(graph); base::Cancellable cancellable; - Algorithm::Params<> params(roadGraph, startPos, finalPos, {} /* prevRoute */, + CHECK(false, ("roadGraph should be duplicated")); + Algorithm::Params<> params(roadGraph, roadGraph, startPos, finalPos, {} /* prevRoute */, cancellable); Algorithm::Result const res = Algorithm().FindPathBidirectional(params, path); From 4b14c956df4df03bc81abffbbb9ed90a7da36c94 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Sun, 11 Oct 2020 08:04:22 +0300 Subject: [PATCH 08/14] Using the same graph for forward and backward waves. --- routing/base/astar_algorithm.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routing/base/astar_algorithm.hpp b/routing/base/astar_algorithm.hpp index 6e1afc78b99..c69a3df465e 100644 --- a/routing/base/astar_algorithm.hpp +++ b/routing/base/astar_algorithm.hpp @@ -618,7 +618,7 @@ AStarAlgorithm::FindPathBidirectional(P & params, { auto const epsilon = params.m_weightEpsilon; auto & graph = params.m_graph; - auto & graphBwd = params.m_graphBwd; + auto & graphBwd = params.m_graph; // params.m_graphBwd; auto const & finalVertex = params.m_finalVertex; auto const & startVertex = params.m_startVertex; From 100a04dcfa010e0fb9cd99700920ca62233e9b86 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Tue, 13 Oct 2020 14:03:54 +0300 Subject: [PATCH 09/14] Some logs were added. --- indexer/feature.cpp | 16 +++++++++++++--- indexer/feature.hpp | 4 ++++ indexer/features_vector.cpp | 2 +- indexer/types_mapping.hpp | 2 +- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/indexer/feature.cpp b/indexer/feature.cpp index 9aba8e23dd8..2528fbd2bfd 100644 --- a/indexer/feature.cpp +++ b/indexer/feature.cpp @@ -196,6 +196,13 @@ FeatureType::FeatureType(SharedLoadInfo const * loadInfo, vector && buf m_header = Header(m_data); } +FeatureType::FeatureType(feature::SharedLoadInfo const * loadInfo, std::vector && buffer, + feature::MetadataIndex const * metadataIndex, uint32_t offset) + : FeatureType(loadInfo, std::move(buffer), metadataIndex) +{ + m_offset = offset; +} + FeatureType::FeatureType(osm::MapObject const & emo) { HeaderGeomType headerGeomType = HeaderGeomType::Point; @@ -275,19 +282,22 @@ void FeatureType::ParseTypes() size_t const count = GetTypesCount(); uint32_t index = 0; + uint32_t type = 0; + size_t i = 0; try { - for (size_t i = 0; i < count; ++i) + for (i = 0; i < count; ++i) { index = ReadVarUint(source); - m_types[i] = c.GetTypeForIndex(index); + type = c.GetTypeForIndex(index); + m_types[i] = type; } } catch (std::out_of_range const & ex) { LOG(LERROR, ("Incorrect type index for feature.FeatureID:", m_id, ". Incorrect index:", index, ". Loaded feature types:", m_types, ". Total count of types:", count, - ". Header:", m_header)); + ". Header:", m_header, "type:", type, "ex:", ex.what(), "i:", i)); throw; } diff --git a/indexer/feature.hpp b/indexer/feature.hpp index bdb7fe62fc8..7ce6b8a4207 100644 --- a/indexer/feature.hpp +++ b/indexer/feature.hpp @@ -37,6 +37,8 @@ class FeatureType FeatureType(feature::SharedLoadInfo const * loadInfo, std::vector && buffer, feature::MetadataIndex const * metadataIndex); FeatureType(osm::MapObject const & emo); + FeatureType(feature::SharedLoadInfo const * loadInfo, std::vector && buffer, + feature::MetadataIndex const * metadataIndex, uint32_t offset); feature::GeomType GetGeomType() const; FeatureParamsBase & GetParams() { return m_params; } @@ -255,5 +257,7 @@ class FeatureType InnerGeomStat m_innerStats; + uint32_t m_offset = 0; + DISALLOW_COPY_AND_MOVE(FeatureType); }; diff --git a/indexer/features_vector.cpp b/indexer/features_vector.cpp index 2ca40eaf959..c65a0350a10 100644 --- a/indexer/features_vector.cpp +++ b/indexer/features_vector.cpp @@ -9,7 +9,7 @@ std::unique_ptr FeaturesVector::GetByIndex(uint32_t index) const { auto const ftOffset = m_table ? m_table->GetFeatureOffset(index) : index; return std::make_unique(&m_loadInfo, m_recordReader->ReadRecord(ftOffset), - m_metaidx.get()); + m_metaidx.get(), ftOffset); } size_t FeaturesVector::GetNumFeatures() const diff --git a/indexer/types_mapping.hpp b/indexer/types_mapping.hpp index 71d3dfec5ed..81939ad9b1f 100644 --- a/indexer/types_mapping.hpp +++ b/indexer/types_mapping.hpp @@ -17,7 +17,7 @@ class IndexAndTypeMapping // Throws std::out_of_range exception. uint32_t GetType(uint32_t ind) const { - ASSERT_LESS ( ind, m_types.size(), () ); + ASSERT_LESS(ind, m_types.size(), ()); return m_types.at(ind); } From 5e858c642d33ff449fc96d330d51ec8af3cfba8a Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Fri, 16 Oct 2020 06:52:39 +0300 Subject: [PATCH 10/14] Found cache that was not ready for multithreading. --- .../coding_tests/var_record_reader_test.cpp | 6 +-- coding/file_reader.cpp | 4 +- coding/var_record_reader.hpp | 3 +- indexer/classificator.hpp | 1 + indexer/data_source.cpp | 2 + indexer/feature.cpp | 38 +++++++++++++++++++ indexer/feature.hpp | 3 ++ indexer/features_offsets_table.cpp | 15 ++++++++ indexer/features_offsets_table.hpp | 3 ++ indexer/features_vector.cpp | 8 +++- indexer/types_mapping.hpp | 2 + routing/base/astar_algorithm.hpp | 3 ++ routing/geometry.cpp | 11 ++++-- routing/index_graph_loader.cpp | 2 + routing/index_router.cpp | 3 +- routing/routing_tests/index_graph_tools.cpp | 4 +- routing/single_vehicle_world_graph.cpp | 38 ++++++++++++++++++- routing/single_vehicle_world_graph.hpp | 5 ++- routing/world_graph.hpp | 2 + track_analyzing/track_analyzer/cmd_tracks.cpp | 2 +- 20 files changed, 139 insertions(+), 16 deletions(-) diff --git a/coding/coding_tests/var_record_reader_test.cpp b/coding/coding_tests/var_record_reader_test.cpp index b32e7aa5e16..b0d6992b453 100644 --- a/coding/coding_tests/var_record_reader_test.cpp +++ b/coding/coding_tests/var_record_reader_test.cpp @@ -52,13 +52,13 @@ UNIT_TEST(VarRecordReader_Simple) MemReader reader(&data[0], data.size()); VarRecordReader recordReader(reader); - auto r = recordReader.ReadRecord(0); + auto r = recordReader.ReadRecord(0, 0); TEST_EQUAL(string(r.begin(), r.end()), "abc", ()); - r = recordReader.ReadRecord(6 + longStringSize); + r = recordReader.ReadRecord(6 + longStringSize, 0); TEST_EQUAL(string(r.begin(), r.end()), "defg", ()); - r = recordReader.ReadRecord(4); + r = recordReader.ReadRecord(4, 0); TEST_EQUAL(string(r.begin(), r.end()), longString, ()); vector> forEachCalls; diff --git a/coding/file_reader.cpp b/coding/file_reader.cpp index 1966935e1e9..f328643496f 100644 --- a/coding/file_reader.cpp +++ b/coding/file_reader.cpp @@ -57,6 +57,7 @@ class FileReader::FileReaderData uint64_t Size() const { return m_fileData.Size(); } +// std::mutex mut; void Read(uint64_t pos, void * p, size_t size) { #if LOG_FILE_READER_STATS @@ -65,7 +66,8 @@ class FileReader::FileReaderData LOG(LINFO, ("FileReader", m_fileData.GetName(), m_readerCache.GetStatsStr())); } #endif - + // TODO This cache should not be accessed from different threads. +// std::lock_guard guard(mut); return m_readerCache.Read(m_fileData, pos, p, size); } diff --git a/coding/var_record_reader.hpp b/coding/var_record_reader.hpp index dbbd388d8d1..8e198b550de 100644 --- a/coding/var_record_reader.hpp +++ b/coding/var_record_reader.hpp @@ -18,7 +18,7 @@ class VarRecordReader public: VarRecordReader(ReaderT const & reader) : m_reader(reader) {} - std::vector ReadRecord(uint64_t const pos) const + std::vector ReadRecord(uint64_t const pos, uint32_t index) const { ReaderSource source(m_reader); ASSERT_LESS(pos, source.Size(), ()); @@ -26,6 +26,7 @@ class VarRecordReader uint32_t const recordSize = ReadVarUint(source); std::vector buffer(recordSize); source.Read(buffer.data(), recordSize); + CheckFeatureTypeData(buffer, pos, index, recordSize); return buffer; } diff --git a/indexer/classificator.hpp b/indexer/classificator.hpp index 471cec8c032..138881465fd 100644 --- a/indexer/classificator.hpp +++ b/indexer/classificator.hpp @@ -185,6 +185,7 @@ class Classificator uint32_t GetIndexForType(uint32_t t) const { return m_mapping.GetIndex(t); } // Throws std::out_of_range exception. uint32_t GetTypeForIndex(uint32_t i) const { return m_mapping.GetType(i); } + bool IsIndexOk(uint32_t ind) const { return m_mapping.IsIndexOk(ind); } bool IsTypeValid(uint32_t t) const { return m_mapping.HasIndex(t); } inline uint32_t GetCoastType() const { return m_coastType; } diff --git a/indexer/data_source.cpp b/indexer/data_source.cpp index 84b10e19ce7..0f7eb5d49ad 100644 --- a/indexer/data_source.cpp +++ b/indexer/data_source.cpp @@ -134,6 +134,7 @@ unique_ptr FeaturesLoaderGuard::GetOriginalOrEditedFeatureByIndex(u unique_ptr FeaturesLoaderGuard::GetFeatureByIndex(uint32_t index) const { + CHECK(m_handle.IsAlive(), ()); if (!m_handle.IsAlive()) return {}; @@ -149,6 +150,7 @@ unique_ptr FeaturesLoaderGuard::GetFeatureByIndex(uint32_t index) c unique_ptr FeaturesLoaderGuard::GetOriginalFeatureByIndex(uint32_t index) const { + CHECK(m_handle.IsAlive(), ()); return m_handle.IsAlive() ? m_source->GetOriginalFeature(index) : nullptr; } diff --git a/indexer/feature.cpp b/indexer/feature.cpp index 2528fbd2bfd..74a50d9cd59 100644 --- a/indexer/feature.cpp +++ b/indexer/feature.cpp @@ -825,3 +825,41 @@ feature::Metadata & FeatureType::GetMetadata() ParseMetadata(); return m_metadata; } + +void CheckFeatureTypeData(std::vector const & data, uint64_t offset, uint32_t fid, + uint32_t recordSize) +{ + static std::atomic counter = 0; + ++counter; + CHECK(!data.empty(), ("offset:", offset, "fid:", fid, "counter:", counter, "recordSize:", recordSize)); + + auto const header = data[0]; + auto const typesOffset = sizeof(header); + Classificator & c = classif(); + ArrayByteSource source(data.data() + typesOffset); + + size_t const count = (header & feature::HEADER_MASK_TYPE) + 1; + uint32_t index = 0; + uint32_t type = 0; + size_t i = 0; + try + { + for (i = 0; i < count; ++i) + { + index = ReadVarUint(source); + type = c.GetTypeForIndex(index); + } + } + catch (std::out_of_range const & ex) + { + LOG(LCRITICAL, ("Incorrect type index:", index, ". header:", header, ". Size of data:", data, + ". count:", count, "type:", type, "ex:", ex.what(), "i:", i, + "Is index ok:", c.IsIndexOk(index) ? "true" : "false", "counter:", counter.load(), "fid:", fid, "offset:", offset)); + for (auto const i : data) + LOG(LINFO, (i)); + throw; + } +// LOG(LINFO, ("Correct type index:", index, ". header:", header, ". Size of data:", data, +// ". count:", count, "type:", type, "i:", i, +// "Is index ok:", c.IsIndexOk(index) ? "true" : "false")); +} diff --git a/indexer/feature.hpp b/indexer/feature.hpp index 7ce6b8a4207..a5e971326e9 100644 --- a/indexer/feature.hpp +++ b/indexer/feature.hpp @@ -261,3 +261,6 @@ class FeatureType DISALLOW_COPY_AND_MOVE(FeatureType); }; + +void CheckFeatureTypeData(std::vector const & data, uint64_t offset, uint32_t index, + uint32_t recordSize); diff --git a/indexer/features_offsets_table.cpp b/indexer/features_offsets_table.cpp index b8acf37f81d..2c1f9ce7ff1 100644 --- a/indexer/features_offsets_table.cpp +++ b/indexer/features_offsets_table.cpp @@ -19,6 +19,8 @@ using namespace std; namespace feature { + bool FeaturesOffsetsTable::m_log = false; + void FeaturesOffsetsTable::Builder::PushOffset(uint32_t const offset) { ASSERT(m_offsets.empty() || m_offsets.back() < offset, ()); @@ -28,10 +30,14 @@ namespace feature FeaturesOffsetsTable::FeaturesOffsetsTable(succinct::elias_fano::elias_fano_builder & builder) : m_table(&builder) { + if (m_log) + LOG(LINFO, ("FeaturesOffsetsTable::FeaturesOffsetsTable()")); } FeaturesOffsetsTable::FeaturesOffsetsTable(string const & filePath) { + if (m_log) + LOG(LINFO, ("FeaturesOffsetsTable::FeaturesOffsetsTable() filePath:", filePath)); m_pReader.reset(new MmapReader(filePath)); succinct::mapper::map(m_table, reinterpret_cast(m_pReader->Data())); } @@ -68,6 +74,9 @@ namespace feature // static unique_ptr FeaturesOffsetsTable::Load(FilesContainerR const & cont) { + if (m_log) + LOG(LINFO, ("FeaturesOffsetsTable::Load()")); + unique_ptr table(new FeaturesOffsetsTable()); table->m_file.Open(cont.GetFileName()); @@ -90,6 +99,8 @@ namespace feature void FeaturesOffsetsTable::Save(string const & filePath) { + if (m_log) + LOG(LINFO, ("FeaturesOffsetsTable::Save()")); LOG(LINFO, ("Saving features offsets table to ", filePath)); string const fileNameTmp = filePath + EXTENSION_TMP; succinct::mapper::freeze(m_table, fileNameTmp.c_str()); @@ -98,12 +109,16 @@ namespace feature uint32_t FeaturesOffsetsTable::GetFeatureOffset(size_t index) const { + if (m_log) + LOG(LINFO, (threads::GetCurrentThreadID(), "FeaturesOffsetsTable::GetFeatureOffset()", index)); ASSERT_LESS(index, size(), ("Index out of bounds", index, size())); return static_cast(m_table.select(index)); } size_t FeaturesOffsetsTable::GetFeatureIndexbyOffset(uint32_t offset) const { + if (m_log) + LOG(LINFO, ("FeaturesOffsetsTable::GetFeatureIndexbyOffset()", offset)); ASSERT_GREATER(size(), 0, ("We must not ask empty table")); ASSERT_LESS_OR_EQUAL(offset, m_table.select(size() - 1), ("Offset out of bounds", offset, m_table.select(size() - 1))); diff --git a/indexer/features_offsets_table.hpp b/indexer/features_offsets_table.hpp index 61e437bc264..fd873eae8d3 100644 --- a/indexer/features_offsets_table.hpp +++ b/indexer/features_offsets_table.hpp @@ -93,6 +93,8 @@ namespace feature /// can be used in benchmarks, logging, etc. // size_t byte_size() { return static_cast(succinct::mapper::size_of(m_table)); } + static void SetLog(bool flag) { m_log = flag; } + private: FeaturesOffsetsTable(succinct::elias_fano::elias_fano_builder & builder); FeaturesOffsetsTable(std::string const & filePath); @@ -105,6 +107,7 @@ namespace feature detail::MappedFile m_file; detail::MappedFile::Handle m_handle; + static bool m_log; }; // Builds feature offsets table in an mwm or rebuilds an existing diff --git a/indexer/features_vector.cpp b/indexer/features_vector.cpp index c65a0350a10..5af843a2c3f 100644 --- a/indexer/features_vector.cpp +++ b/indexer/features_vector.cpp @@ -1,4 +1,5 @@ #include "features_vector.hpp" +#include "feature.hpp" #include "features_offsets_table.hpp" #include "data_factory.hpp" @@ -7,8 +8,11 @@ std::unique_ptr FeaturesVector::GetByIndex(uint32_t index) const { - auto const ftOffset = m_table ? m_table->GetFeatureOffset(index) : index; - return std::make_unique(&m_loadInfo, m_recordReader->ReadRecord(ftOffset), + uint32_t ftOffset = 0; + ftOffset = m_table ? m_table->GetFeatureOffset(index) : index; +// if (index == 333004 || index == 468000 || index == 664105) +// LOG(LCRITICAL, (index, ftOffset)); + return std::make_unique(&m_loadInfo, m_recordReader->ReadRecord(ftOffset, index), m_metaidx.get(), ftOffset); } diff --git a/indexer/types_mapping.hpp b/indexer/types_mapping.hpp index 81939ad9b1f..1e32e065d09 100644 --- a/indexer/types_mapping.hpp +++ b/indexer/types_mapping.hpp @@ -21,6 +21,8 @@ class IndexAndTypeMapping return m_types.at(ind); } + bool IsIndexOk(uint32_t ind) const { return ind < m_types.size(); } + uint32_t GetIndex(uint32_t t) const; /// For Debug purposes only. diff --git a/routing/base/astar_algorithm.hpp b/routing/base/astar_algorithm.hpp index c69a3df465e..79dc7ba836f 100644 --- a/routing/base/astar_algorithm.hpp +++ b/routing/base/astar_algorithm.hpp @@ -5,6 +5,8 @@ #include "routing/base/astar_weight.hpp" #include "routing/base/routing_result.hpp" +#include "indexer/features_offsets_table.hpp" + #include "base/assert.hpp" #include "base/cancellable.hpp" #include "base/fifo_cache.hpp" @@ -712,6 +714,7 @@ AStarAlgorithm::FindPathBidirectional(P & params, // Starting a thread. { +// feature::FeaturesOffsetsTable::SetLog(true); base::ScopedTimerWithLog timer("Wave"); auto backwardWave = std::async(std::launch::async, wave, std::ref(backward), std::ref(bwdIsEmpty), std::ref(forward), std::ref(fwdIsEmpty)); diff --git a/routing/geometry.cpp b/routing/geometry.cpp index 65f80f94e81..902249ffec1 100644 --- a/routing/geometry.cpp +++ b/routing/geometry.cpp @@ -16,6 +16,7 @@ #include "base/string_utils.hpp" #include +#include #include using namespace routing; @@ -92,20 +93,24 @@ GeometryLoaderImpl::GeometryLoaderImpl(DataSource const & dataSource, CHECK(m_attrLoader.m_maxspeeds, ()); } +//std::mutex mtx; + void GeometryLoaderImpl::Load(uint32_t featureId, RoadGeometry & road) { +// std::unique_lock guard(mtx); auto feature = m_guard.GetFeatureByIndex(featureId); if (!feature) MYTHROW(RoutingException, ("Feature", featureId, "not found in ", m_country)); feature->ParseGeometry(FeatureType::BEST_GEOMETRY); +// guard.unlock(); geometry::Altitudes const * altitudes = nullptr; // if (m_loadAltitudes) // altitudes = &(m_altitudeLoader.GetAltitudes(featureId, feature->GetPointsCount())); - road.Load(*m_vehicleModel, *feature, altitudes, m_attrLoader.m_cityRoads->IsCityRoad(featureId), - m_attrLoader.m_maxspeeds->GetMaxspeed(featureId)); +// road.Load(*m_vehicleModel, *feature, altitudes, m_attrLoader.m_cityRoads->IsCityRoad(featureId), +// m_attrLoader.m_maxspeeds->GetMaxspeed(featureId)); // m_altitudeLoader.ClearCache(); } @@ -185,7 +190,7 @@ void RoadGeometry::Load(VehicleModelInterface const & vehicleModel, FeatureType { CHECK(altitudes == nullptr || altitudes->size() == feature.GetPointsCount(), ()); - m_valid = vehicleModel.IsRoad(feature); + vehicleModel.IsRoad(feature); m_isOneWay = vehicleModel.IsOneWay(feature); m_forwardSpeed = vehicleModel.GetSpeed(feature, {true /* forward */, inCity, maxspeed}); m_backwardSpeed = vehicleModel.GetSpeed(feature, {false /* forward */, inCity, maxspeed}); diff --git a/routing/index_graph_loader.cpp b/routing/index_graph_loader.cpp index 48c9f97f511..23c3ad2db26 100644 --- a/routing/index_graph_loader.cpp +++ b/routing/index_graph_loader.cpp @@ -196,10 +196,12 @@ vector IndexGraphLoaderImpl::GetSpeedCameraInfo(Segme IndexGraphLoaderImpl::GraphAttrs & IndexGraphLoaderImpl::CreateGeometry(NumMwmId numMwmId) { platform::CountryFile const & file = m_numMwmIds->GetFile(numMwmId); + // @TODO No protection!!!!! MwmSet::MwmHandle handle = m_dataSource.GetMwmHandleByCountryFile(file); if (!handle.IsAlive()) MYTHROW(RoutingException, ("Can't get mwm handle for", file)); + // @TODO No protection!!!!! shared_ptr vehicleModel = m_vehicleModelFactory->GetVehicleModelForCountry(file.GetName()); diff --git a/routing/index_router.cpp b/routing/index_router.cpp index 0a9f1435caf..01606bbef32 100644 --- a/routing/index_router.cpp +++ b/routing/index_router.cpp @@ -588,6 +588,7 @@ RouterResultCode IndexRouter::DoCalculateRoute(Checkpoints const & checkpoints, TrafficStash::Guard guard(m_trafficStash); unique_ptr graph = MakeWorldGraph(); + graph->MultithreadingIssue(m_dataSource); vector segments; @@ -1034,7 +1035,7 @@ unique_ptr IndexRouter::MakeWorldGraph() { auto graph = make_unique( move(crossMwmGraph), move(indexGraphLoader), m_estimator, - MwmHierarchyHandler(m_numMwmIds, m_countryParentNameGetterFn)); + MwmHierarchyHandler(m_numMwmIds, m_countryParentNameGetterFn), m_numMwmIds); graph->SetRoutingOptions(routingOptions); return graph; } diff --git a/routing/routing_tests/index_graph_tools.cpp b/routing/routing_tests/index_graph_tools.cpp index a839ca365d8..6a767e13564 100644 --- a/routing/routing_tests/index_graph_tools.cpp +++ b/routing/routing_tests/index_graph_tools.cpp @@ -420,7 +420,7 @@ unique_ptr BuildWorldGraph(unique_ptr(); indexLoader->AddGraph(kTestNumMwmId, move(graph)); return make_unique(nullptr /* crossMwmGraph */, move(indexLoader), - estimator, MwmHierarchyHandler(nullptr, nullptr)); + estimator, MwmHierarchyHandler(nullptr, nullptr), nullptr); } unique_ptr BuildIndexGraph(unique_ptr geometryLoader, @@ -442,7 +442,7 @@ unique_ptr BuildWorldGraph(unique_ptr(); indexLoader->AddGraph(kTestNumMwmId, move(graph)); return make_unique(nullptr /* crossMwmGraph */, move(indexLoader), - estimator, MwmHierarchyHandler(nullptr, nullptr)); + estimator, MwmHierarchyHandler(nullptr, nullptr), nullptr); } unique_ptr BuildWorldGraph(unique_ptr geometryLoader, diff --git a/routing/single_vehicle_world_graph.cpp b/routing/single_vehicle_world_graph.cpp index 1e683273f8e..08a85435765 100644 --- a/routing/single_vehicle_world_graph.cpp +++ b/routing/single_vehicle_world_graph.cpp @@ -22,16 +22,52 @@ SingleVehicleWorldGraph::AStarParents::kEmpty = {}; SingleVehicleWorldGraph::SingleVehicleWorldGraph(unique_ptr crossMwmGraph, unique_ptr loader, shared_ptr estimator, - MwmHierarchyHandler && hierarchyHandler) + MwmHierarchyHandler && hierarchyHandler, + std::shared_ptr numMwmIds) : m_crossMwmGraph(move(crossMwmGraph)) , m_loader(move(loader)) , m_estimator(move(estimator)) , m_hierarchyHandler(std::move(hierarchyHandler)) + , m_numMwmIds(std::move(numMwmIds)) { CHECK(m_loader, ()); CHECK(m_estimator, ()); } +void SingleVehicleWorldGraph::MultithreadingIssue(DataSource & dataSource) +{ + LOG(LINFO, ("SingleVehicleWorldGraph::MultithreadingIssue()")); +// auto & mosGeom = m_loader->GetGeometry(749 /* Moscow */); + platform::CountryFile const & file = m_numMwmIds->GetFile(749 /* Moscow */); + MwmSet::MwmHandle handle = dataSource.GetMwmHandleByCountryFile(file); + if (!handle.IsAlive()) + MYTHROW(RoutingException, ("Can't get mwm handle for", file)); + FeaturesLoaderGuard m_guard(dataSource, handle.GetId()); + auto wave = [&](bool isOutgoing){ + LOG(LINFO, ("SingleVehicleWorldGraph::MultithreadingIssue() --------- wave ---------", isOutgoing)); + size_t pointCounts = 0; + for (uint32_t i = 1; i < 600'000; ++i) + { +// RoadGeometry const & road = mosGeom.GetRoad(i, isOutgoing); +// RoadGeometry road; +// mosGeom.LoadGeomLock(i, road); +// pointCounts += road.GetPointsCount(); + + auto feature = m_guard.GetFeatureByIndex(i); + if (!feature) + MYTHROW(RoutingException, ("Feature", i, "not found in Moscow.")); + + feature->ParseGeometry(FeatureType::BEST_GEOMETRY); + pointCounts += feature->GetPointsCount(); + } + LOG(LINFO, ("SingleVehicleWorldGraph::MultithreadingIssue() --------- wave end ----", isOutgoing, pointCounts)); + }; + auto backwardWave = std::async(std::launch::async, wave, false /* isOutgoing */); + wave(true /* isOutgoing */); + backwardWave.get(); + LOG(LINFO, ("SingleVehicleWorldGraph::MultithreadingIssue() end.")); +} + void SingleVehicleWorldGraph::CheckAndProcessTransitFeatures(Segment const & parent, vector & jointEdges, vector & parentWeights, diff --git a/routing/single_vehicle_world_graph.hpp b/routing/single_vehicle_world_graph.hpp index d133a543354..6546c3f739d 100644 --- a/routing/single_vehicle_world_graph.hpp +++ b/routing/single_vehicle_world_graph.hpp @@ -31,7 +31,9 @@ class SingleVehicleWorldGraph final : public WorldGraph SingleVehicleWorldGraph(std::unique_ptr crossMwmGraph, std::unique_ptr loader, std::shared_ptr estimator, - MwmHierarchyHandler && hierarchyHandler); + MwmHierarchyHandler && hierarchyHandler, std::shared_ptr numMwmIds); + + void MultithreadingIssue(DataSource & dataSource) override; // WorldGraph overrides: // @{ @@ -145,5 +147,6 @@ class SingleVehicleWorldGraph final : public WorldGraph AStarParents m_parentsForJoints; MwmHierarchyHandler m_hierarchyHandler; + std::shared_ptr m_numMwmIds; }; } // namespace routing diff --git a/routing/world_graph.hpp b/routing/world_graph.hpp index 6146df5dcab..32861282f96 100644 --- a/routing/world_graph.hpp +++ b/routing/world_graph.hpp @@ -50,6 +50,8 @@ class WorldGraph virtual ~WorldGraph() = default; + virtual void MultithreadingIssue(DataSource & dataSource) {} + virtual void GetEdgeList(astar::VertexData const & vertexData, bool isOutgoing, bool useRoutingOptions, bool useAccessConditional, std::vector & edges) = 0; diff --git a/track_analyzing/track_analyzer/cmd_tracks.cpp b/track_analyzing/track_analyzer/cmd_tracks.cpp index 1f54e28dbfa..3e68afe6f8b 100644 --- a/track_analyzing/track_analyzer/cmd_tracks.cpp +++ b/track_analyzing/track_analyzer/cmd_tracks.cpp @@ -116,7 +116,7 @@ double EstimateDuration(MatchedTrack const & track, shared_ptr es segment = point.GetSegment(); result += estimator->CalcSegmentWeight(segment, geometry.GetRoad(segment.GetFeatureId(), true /* isOutgoing */), - EdgeEstimator::Purpose::ETA); + EdgeEstimator::Purpose::ETA, true); } return result; From 7e194c1b9eeeb6f736025c559c31462622e8c687 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Sun, 18 Oct 2020 07:45:46 +0300 Subject: [PATCH 11/14] Recovering workable state of project (Stop executing some test code and so on). --- coding/var_record_reader.hpp | 2 ++ routing/base/astar_algorithm.hpp | 34 ++------------------------ routing/geometry.cpp | 7 +++--- routing/index_graph_loader.cpp | 8 +++--- routing/index_graph_starter_joints.hpp | 2 ++ routing/index_router.cpp | 2 +- routing/single_vehicle_world_graph.cpp | 11 +++------ 7 files changed, 18 insertions(+), 48 deletions(-) diff --git a/coding/var_record_reader.hpp b/coding/var_record_reader.hpp index 8e198b550de..f003b9c8ea1 100644 --- a/coding/var_record_reader.hpp +++ b/coding/var_record_reader.hpp @@ -1,5 +1,7 @@ #pragma once +#include "indexer/feature.hpp" + #include "coding/byte_stream.hpp" #include "coding/reader.hpp" #include "coding/varint.hpp" diff --git a/routing/base/astar_algorithm.hpp b/routing/base/astar_algorithm.hpp index 79dc7ba836f..ddd0b297568 100644 --- a/routing/base/astar_algorithm.hpp +++ b/routing/base/astar_algorithm.hpp @@ -287,9 +287,6 @@ class AStarAlgorithm , startVertex(startVertex) , finalVertex(finalVertex) , graph(graph) -// , consistentHeuristics(300 /* capacity */, [this](Vertex const & v, Weight & w) { -// this->ConsistentHeuristicImpl(v, w); -// }) { bestVertex = forward ? startVertex : finalVertex; pS = ConsistentHeuristic(bestVertex); @@ -320,10 +317,8 @@ class AStarAlgorithm // particular routes when debugging turned out to be easier. Weight ConsistentHeuristic(Vertex const & v) const { - Weight piF; - Weight piR; - piF = graph.HeuristicCostEstimate(v, finalVertex, forward); - piR = graph.HeuristicCostEstimate(v, startVertex, forward); + Weight piF = graph.HeuristicCostEstimate(v, finalVertex, forward); + Weight piR = graph.HeuristicCostEstimate(v, startVertex, forward); if (forward) { @@ -338,28 +333,6 @@ class AStarAlgorithm return 0.5 * (piR - piF); } } -// void ConsistentHeuristicImpl(Vertex const & v, Weight & weight) const -// { -// auto const piF = graph.HeuristicCostEstimate(v, finalVertex); -// auto const piR = graph.HeuristicCostEstimate(v, startVertex); -// if (forward) -// { -// /// @todo careful: with this "return" here and below in the Backward case -// /// the heuristic becomes inconsistent but still seems to work. -// /// return HeuristicCostEstimate(v, finalVertex); -// weight = 0.5 * (piF - piR); -// } -// else -// { -// // return HeuristicCostEstimate(v, startVertex); -// weight = 0.5 * (piR - piF); -// } -// } -// -// Weight ConsistentHeuristic(Vertex const & v) -// { -// return consistentHeuristics.GetValue(v); -// } bool ExistsStateWithBetterDistance(State const & state, Weight const & eps = Weight(0.0)) const { @@ -415,7 +388,6 @@ class AStarAlgorithm return GetDistance(vertex); } -// std::atomic fullProtection; std::mutex & mtx; std::mutex & mtxGr; bool const forward; @@ -425,7 +397,6 @@ class AStarAlgorithm std::priority_queue, std::greater> queue; ska::bytell_hash_map bestDistance; -// FifoCache consistentHeuristics; Parents parent; Vertex bestVertex; @@ -1007,7 +978,6 @@ AStarAlgorithm::FindPathBidirectionalOneThread(P & params, return Result::NoPath; } - template template typename AStarAlgorithm::Result diff --git a/routing/geometry.cpp b/routing/geometry.cpp index 902249ffec1..bf71cc16756 100644 --- a/routing/geometry.cpp +++ b/routing/geometry.cpp @@ -109,8 +109,8 @@ void GeometryLoaderImpl::Load(uint32_t featureId, RoadGeometry & road) // if (m_loadAltitudes) // altitudes = &(m_altitudeLoader.GetAltitudes(featureId, feature->GetPointsCount())); -// road.Load(*m_vehicleModel, *feature, altitudes, m_attrLoader.m_cityRoads->IsCityRoad(featureId), -// m_attrLoader.m_maxspeeds->GetMaxspeed(featureId)); + road.Load(*m_vehicleModel, *feature, altitudes, m_attrLoader.m_cityRoads->IsCityRoad(featureId), + m_attrLoader.m_maxspeeds->GetMaxspeed(featureId)); // m_altitudeLoader.ClearCache(); } @@ -190,8 +190,7 @@ void RoadGeometry::Load(VehicleModelInterface const & vehicleModel, FeatureType { CHECK(altitudes == nullptr || altitudes->size() == feature.GetPointsCount(), ()); - vehicleModel.IsRoad(feature); - m_isOneWay = vehicleModel.IsOneWay(feature); + m_valid = vehicleModel.IsRoad(feature); m_forwardSpeed = vehicleModel.GetSpeed(feature, {true /* forward */, inCity, maxspeed}); m_backwardSpeed = vehicleModel.GetSpeed(feature, {false /* forward */, inCity, maxspeed}); m_highwayType = vehicleModel.GetHighwayType(feature); diff --git a/routing/index_graph_loader.cpp b/routing/index_graph_loader.cpp index 23c3ad2db26..e5264fa40fb 100644 --- a/routing/index_graph_loader.cpp +++ b/routing/index_graph_loader.cpp @@ -55,7 +55,7 @@ class IndexGraphLoaderImpl final : public IndexGraphLoader VehicleType m_vehicleType; bool m_loadAltitudes; - std::mutex m_dataSourceMtx; +// std::mutex m_dataSourceMtx; DataSource & m_dataSource; shared_ptr m_numMwmIds; shared_ptr m_vehicleModelFactory; @@ -205,10 +205,12 @@ IndexGraphLoaderImpl::GraphAttrs & IndexGraphLoaderImpl::CreateGeometry(NumMwmId shared_ptr vehicleModel = m_vehicleModelFactory->GetVehicleModelForCountry(file.GetName()); + auto geom = make_shared(GeometryLoader::Create( + m_dataSource, handle, vehicleModel, AttrLoader(m_dataSource, handle), m_loadAltitudes)); + std::lock_guard guard(m_graphsMtx); auto & graph = m_graphs[numMwmId]; - graph.m_geometry = make_shared(GeometryLoader::Create( - m_dataSource, handle, vehicleModel, AttrLoader(m_dataSource, handle), m_loadAltitudes)); + graph.m_geometry = std::move(geom); return graph; } diff --git a/routing/index_graph_starter_joints.hpp b/routing/index_graph_starter_joints.hpp index effe35eeb19..002d0398900 100644 --- a/routing/index_graph_starter_joints.hpp +++ b/routing/index_graph_starter_joints.hpp @@ -544,6 +544,8 @@ void IndexGraphStarterJoints::GetEdgeList( // |parentSegment| is parent-vertex from which we search children. // For correct weight calculation we should get weight of JointSegment, that // ends in |parentSegment| and add |parentWeight[i]| to the saved value. + + // @TODO It seems this guards is taken too often. std::lock_guard guard(m_savedWeightMtx); auto const it = m_savedWeight.find(vertex); CHECK(it != m_savedWeight.cend(), ("Can not find weight for:", vertex)); diff --git a/routing/index_router.cpp b/routing/index_router.cpp index 01606bbef32..6dfda3411e8 100644 --- a/routing/index_router.cpp +++ b/routing/index_router.cpp @@ -588,7 +588,7 @@ RouterResultCode IndexRouter::DoCalculateRoute(Checkpoints const & checkpoints, TrafficStash::Guard guard(m_trafficStash); unique_ptr graph = MakeWorldGraph(); - graph->MultithreadingIssue(m_dataSource); +// graph->MultithreadingIssue(m_dataSource); vector segments; diff --git a/routing/single_vehicle_world_graph.cpp b/routing/single_vehicle_world_graph.cpp index 08a85435765..7e580e7bce1 100644 --- a/routing/single_vehicle_world_graph.cpp +++ b/routing/single_vehicle_world_graph.cpp @@ -37,23 +37,18 @@ SingleVehicleWorldGraph::SingleVehicleWorldGraph(unique_ptr cross void SingleVehicleWorldGraph::MultithreadingIssue(DataSource & dataSource) { LOG(LINFO, ("SingleVehicleWorldGraph::MultithreadingIssue()")); -// auto & mosGeom = m_loader->GetGeometry(749 /* Moscow */); platform::CountryFile const & file = m_numMwmIds->GetFile(749 /* Moscow */); MwmSet::MwmHandle handle = dataSource.GetMwmHandleByCountryFile(file); if (!handle.IsAlive()) MYTHROW(RoutingException, ("Can't get mwm handle for", file)); - FeaturesLoaderGuard m_guard(dataSource, handle.GetId()); + auto wave = [&](bool isOutgoing){ LOG(LINFO, ("SingleVehicleWorldGraph::MultithreadingIssue() --------- wave ---------", isOutgoing)); + FeaturesLoaderGuard guard(dataSource, handle.GetId()); size_t pointCounts = 0; for (uint32_t i = 1; i < 600'000; ++i) { -// RoadGeometry const & road = mosGeom.GetRoad(i, isOutgoing); -// RoadGeometry road; -// mosGeom.LoadGeomLock(i, road); -// pointCounts += road.GetPointsCount(); - - auto feature = m_guard.GetFeatureByIndex(i); + auto feature = guard.GetFeatureByIndex(i); if (!feature) MYTHROW(RoutingException, ("Feature", i, "not found in Moscow.")); From 788db06079374d9faf408850db06bd1fa16e91a1 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Sun, 18 Oct 2020 08:38:57 +0300 Subject: [PATCH 12/14] Using two guards from two threads. --- .../routing_helpers.hpp | 2 +- routing/geometry.cpp | 24 +++++++++++-------- routing/geometry.hpp | 6 ++--- routing/routing_tests/index_graph_tools.cpp | 2 +- routing/routing_tests/index_graph_tools.hpp | 2 +- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/generator/generator_tests_support/routing_helpers.hpp b/generator/generator_tests_support/routing_helpers.hpp index bc5387d0704..10ded47d619 100644 --- a/generator/generator_tests_support/routing_helpers.hpp +++ b/generator/generator_tests_support/routing_helpers.hpp @@ -31,7 +31,7 @@ class TestGeometryLoader : public GeometryLoader { public: // GeometryLoader overrides: - void Load(uint32_t featureId, routing::RoadGeometry & road) override; + void Load(uint32_t featureId, bool isOutgoing, routing::RoadGeometry & road) override; void AddRoad(uint32_t featureId, bool oneWay, float speed, routing::RoadGeometry::Points const & points); diff --git a/routing/geometry.cpp b/routing/geometry.cpp index bf71cc16756..3f71db74045 100644 --- a/routing/geometry.cpp +++ b/routing/geometry.cpp @@ -65,12 +65,13 @@ class GeometryLoaderImpl final : public GeometryLoader AttrLoader attrLoader, bool loadAltitudes); // GeometryLoader overrides: - void Load(uint32_t featureId, RoadGeometry & road) override; + void Load(uint32_t featureId, bool isOutgoing, RoadGeometry & road) override; private: shared_ptr m_vehicleModel; AttrLoader m_attrLoader; FeaturesLoaderGuard m_guard; + FeaturesLoaderGuard m_guardBwd; string const m_country; feature::AltitudeLoader m_altitudeLoader; bool const m_loadAltitudes; @@ -83,6 +84,7 @@ GeometryLoaderImpl::GeometryLoaderImpl(DataSource const & dataSource, : m_vehicleModel(move(vehicleModel)) , m_attrLoader(move(attrLoader)) , m_guard(dataSource, handle.GetId()) + , m_guardBwd(dataSource, handle.GetId()) , m_country(handle.GetInfo()->GetCountryName()) , m_altitudeLoader(dataSource, handle.GetId()) , m_loadAltitudes(loadAltitudes) @@ -95,14 +97,15 @@ GeometryLoaderImpl::GeometryLoaderImpl(DataSource const & dataSource, //std::mutex mtx; -void GeometryLoaderImpl::Load(uint32_t featureId, RoadGeometry & road) +void GeometryLoaderImpl::Load(uint32_t featureId, bool isOutgoing, RoadGeometry & road) { // std::unique_lock guard(mtx); - auto feature = m_guard.GetFeatureByIndex(featureId); - if (!feature) - MYTHROW(RoutingException, ("Feature", featureId, "not found in ", m_country)); +auto feature = + isOutgoing ? m_guard.GetFeatureByIndex(featureId) : m_guardBwd.GetFeatureByIndex(featureId); +if (!feature) + MYTHROW(RoutingException, ("Feature", featureId, "not found in ", m_country)); - feature->ParseGeometry(FeatureType::BEST_GEOMETRY); +feature->ParseGeometry(FeatureType::BEST_GEOMETRY); // guard.unlock(); geometry::Altitudes const * altitudes = nullptr; @@ -121,7 +124,7 @@ class FileGeometryLoader final : public GeometryLoader FileGeometryLoader(string const & fileName, shared_ptr vehicleModel); // GeometryLoader overrides: - void Load(uint32_t featureId, RoadGeometry & road) override; + void Load(uint32_t featureId, bool isOutgoing, RoadGeometry & road) override; private: FeaturesVectorTest m_featuresVector; @@ -154,8 +157,9 @@ FileGeometryLoader::FileGeometryLoader(string const & fileName, CHECK(m_vehicleModel, ()); } -void FileGeometryLoader::Load(uint32_t featureId, RoadGeometry & road) +void FileGeometryLoader::Load(uint32_t featureId, bool isOutgoing, RoadGeometry & road) { + CHECK(false, ("FileGeometryLoader() is not ready for multithreading.")); auto feature = m_featuresVector.GetVector().GetByIndex(featureId); CHECK(feature, ()); feature->ParseGeometry(FeatureType::BEST_GEOMETRY); @@ -261,10 +265,10 @@ Geometry::Geometry(unique_ptr loader) : m_loader(move(loader)) , m_featureIdToRoad(make_unique( kRoadsCacheSize, - [this](uint32_t featureId, RoadGeometry & road) { LoadGeomLock(featureId, road); })) + [this](uint32_t featureId, RoadGeometry & road) { LoadGeomLock(featureId, true /* isOutgoing */, road); })) , m_featureIdToRoadBwd(make_unique( kRoadsCacheSize, - [this](uint32_t featureId, RoadGeometry & road) { LoadGeomLock(featureId, road); })) + [this](uint32_t featureId, RoadGeometry & road) { LoadGeomLock(featureId, false /* isOutgoing */, road); })) { CHECK(m_loader, ()); } diff --git a/routing/geometry.hpp b/routing/geometry.hpp index cff34518768..975641a382b 100644 --- a/routing/geometry.hpp +++ b/routing/geometry.hpp @@ -109,7 +109,7 @@ class GeometryLoader public: virtual ~GeometryLoader() = default; - virtual void Load(uint32_t featureId, RoadGeometry & road) = 0; + virtual void Load(uint32_t featureId, bool isOutgoing, RoadGeometry & road) = 0; // handle should be alive: it is caller responsibility to check it. static std::unique_ptr Create(DataSource const & dataSource, @@ -149,10 +149,10 @@ class Geometry final return GetRoad(rp.GetFeatureId(), isOutgoing).GetPoint(rp.GetPointId()); } - void LoadGeomLock(uint32_t featureId, RoadGeometry & road) + void LoadGeomLock(uint32_t featureId, bool isOutgoing, RoadGeometry & road) { // std::lock_guard lock(m_loaderMtx); - m_loader->Load(featureId, road); + m_loader->Load(featureId, isOutgoing, road); } private: diff --git a/routing/routing_tests/index_graph_tools.cpp b/routing/routing_tests/index_graph_tools.cpp index 6a767e13564..7a659003171 100644 --- a/routing/routing_tests/index_graph_tools.cpp +++ b/routing/routing_tests/index_graph_tools.cpp @@ -101,7 +101,7 @@ void NoUTurnRestrictionTest::TestRouteGeom(Segment const & start, Segment const } // ZeroGeometryLoader ------------------------------------------------------------------------------ -void ZeroGeometryLoader::Load(uint32_t /* featureId */, routing::RoadGeometry & road) +void ZeroGeometryLoader::Load(uint32_t /* featureId */, bool isOutgoing, routing::RoadGeometry & road) { // Any valid road will do. auto const points = routing::RoadGeometry::Points({{0.0, 0.0}, {0.0, 1.0}}); diff --git a/routing/routing_tests/index_graph_tools.hpp b/routing/routing_tests/index_graph_tools.hpp index 6e8d9776480..598253579fe 100644 --- a/routing/routing_tests/index_graph_tools.hpp +++ b/routing/routing_tests/index_graph_tools.hpp @@ -119,7 +119,7 @@ class ZeroGeometryLoader final : public routing::GeometryLoader // GeometryLoader overrides: ~ZeroGeometryLoader() override = default; - void Load(uint32_t featureId, routing::RoadGeometry & road) override; + void Load(uint32_t featureId, bool isOutgoing, routing::RoadGeometry & road) override; }; class TestIndexGraphLoader final : public IndexGraphLoader From 898c97dad207147e10ded2fddbdf27da76aa6083 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Tue, 20 Oct 2020 08:28:07 +0300 Subject: [PATCH 13/14] Removing m_savedWeightMtx. --- routing/index_graph_starter_joints.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/routing/index_graph_starter_joints.hpp b/routing/index_graph_starter_joints.hpp index 002d0398900..b926c46dbe8 100644 --- a/routing/index_graph_starter_joints.hpp +++ b/routing/index_graph_starter_joints.hpp @@ -194,7 +194,7 @@ class IndexGraphStarterJoints : public AStarGraph m_savedWeight; // JointSegment consists of two segments of one feature. @@ -289,7 +289,7 @@ void IndexGraphStarterJoints::InitEnding(Segment const & ending, bool sta if (!start) { - std::lock_guard guard(m_savedWeightMtx); +// std::lock_guard guard(m_savedWeightMtx); // Initialization before starting two threads. m_savedWeight[m_endJoint] = Weight(0.0); for (auto const & edge : m_endOutEdges) m_savedWeight[edge.GetTarget()] = edge.GetWeight(); @@ -439,7 +439,7 @@ std::optional IndexGraphStarterJoints::GetParentSegment( } else { - std::lock_guard guard(m_savedWeightMtx); +// std::lock_guard guard(m_savedWeightMtx); auto const it = m_savedWeight.find(vertex); CHECK(it != m_savedWeight.cend(), ("Can not find weight for:", vertex)); @@ -546,7 +546,7 @@ void IndexGraphStarterJoints::GetEdgeList( // ends in |parentSegment| and add |parentWeight[i]| to the saved value. // @TODO It seems this guards is taken too often. - std::lock_guard guard(m_savedWeightMtx); +// std::lock_guard guard(m_savedWeightMtx); auto const it = m_savedWeight.find(vertex); CHECK(it != m_savedWeight.cend(), ("Can not find weight for:", vertex)); @@ -705,7 +705,7 @@ void IndexGraphStarterJoints::Reset() m_startSegment = Segment(); m_endSegment = Segment(); { - std::lock_guard guard(m_savedWeightMtx); +// std::lock_guard guard(m_savedWeightMtx); m_savedWeight.clear(); } m_fakeJointSegments.clear(); From 40eb4e094c747c74a196a28a7ffa486808b3794a Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Tue, 20 Oct 2020 17:46:42 +0300 Subject: [PATCH 14/14] Commenting checking SegmentsAreEqualByGeometry() if different version of mwms have different geometry of transition features. --- routing/cross_mwm_index_graph.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/routing/cross_mwm_index_graph.hpp b/routing/cross_mwm_index_graph.hpp index f4a5a12ae77..b1528a90bf3 100644 --- a/routing/cross_mwm_index_graph.hpp +++ b/routing/cross_mwm_index_graph.hpp @@ -139,10 +139,10 @@ class CrossMwmIndexGraph final // There are same in common, but in case of different version of mwms // their's geometry can differ from each other. Because of this we can not // build the route, because we fail in astar_algorithm.hpp CHECK(invariant) sometimes. - if (SegmentsAreEqualByGeometry(s, *twinSeg)) +// if (SegmentsAreEqualByGeometry(s, *twinSeg)) twins.push_back(*twinSeg); - else - LOG(LINFO, ("Bad cross mwm feature, differ in geometry. Current:", s, ", twin:", *twinSeg)); +// else +// LOG(LINFO, ("Bad cross mwm feature, differ in geometry. Current:", s, ", twin:", *twinSeg)); } } @@ -164,6 +164,7 @@ class CrossMwmIndexGraph final CrossMwmConnector const & GetCrossMwmConnectorWithTransitions(NumMwmId numMwmId) { + // @TODO |m_connectors| should be protected. auto const it = m_connectors.find(numMwmId); if (it != m_connectors.cend()) return it->second;