diff --git a/routing/osrm2feature_map.cpp b/routing/osrm2feature_map.cpp index 1af5df7bd1..b62d707bff 100644 --- a/routing/osrm2feature_map.cpp +++ b/routing/osrm2feature_map.cpp @@ -161,7 +161,7 @@ void OsrmFtSegMapping::DumpSegmentByNode(OsrmNodeIdT nodeId) const } -void OsrmFtSegMapping::GetOsrmNodes(FtSegSetT & segments, OsrmNodesT & res) const +void OsrmFtSegMapping::GetOsrmNodes(FtSegSetT & segments, OsrmNodesT & res, volatile bool const & requestCancel) const { auto addResFn = [&](uint64_t seg, size_t idx, bool forward) { @@ -191,6 +191,9 @@ void OsrmFtSegMapping::GetOsrmNodes(FtSegSetT & segments, OsrmNodesT & res) cons { FtSeg s(m_segments[i]); + if (requestCancel) + return; + for (auto it = segments.begin(); it != segments.end(); ++it) { FtSeg const & seg = *(*it); diff --git a/routing/osrm2feature_map.hpp b/routing/osrm2feature_map.hpp index 67bd344a0f..9272d7bafa 100644 --- a/routing/osrm2feature_map.hpp +++ b/routing/osrm2feature_map.hpp @@ -101,7 +101,7 @@ public: } typedef unordered_map > OsrmNodesT; - void GetOsrmNodes(FtSegSetT & segments, OsrmNodesT & res) const; + void GetOsrmNodes(FtSegSetT & segments, OsrmNodesT & res, volatile bool const & requestCancel) const; /// @name For debug purpose only. //@{ diff --git a/routing/osrm_router.cpp b/routing/osrm_router.cpp index 63befcd5bb..a6ad07cadf 100644 --- a/routing/osrm_router.cpp +++ b/routing/osrm_router.cpp @@ -104,7 +104,8 @@ public: m_candidates[m_ptIdx].push_back(res); } - void MakeResult(OsrmRouter::FeatureGraphNodeVecT & res, size_t maxCount, uint32_t & mwmId, bool needFinal) + void MakeResult(OsrmRouter::FeatureGraphNodeVecT & res, size_t maxCount, uint32_t & mwmId, + bool needFinal, volatile bool const & requestCancel) { mwmId = m_mwmId; if (mwmId == numeric_limits::max()) @@ -138,7 +139,7 @@ public: } OsrmFtSegMapping::OsrmNodesT nodes; - m_mapping.GetOsrmNodes(segmentSet, nodes); + m_mapping.GetOsrmNodes(segmentSet, nodes, requestCancel); res.clear(); res.resize(maxCount * 2); @@ -169,7 +170,8 @@ public: OsrmRouter::OsrmRouter(Index const * index, CountryFileFnT const & fn) - : m_countryFn(fn), m_pIndex(index), m_isFinalChanged(false), m_isReadyThread(false) + : m_countryFn(fn), m_pIndex(index), m_isFinalChanged(false), + m_isReadyThread(false), m_requestCancel(false) { } @@ -180,19 +182,32 @@ string OsrmRouter::GetName() const void OsrmRouter::SetFinalPoint(m2::PointD const & finalPt) { - threads::MutexGuard guard(m_paramsMutex); - UNUSED_VALUE(guard); + { + threads::MutexGuard guard(m_paramsMutex); + UNUSED_VALUE(guard); - m_finalPt = finalPt; - m_isFinalChanged = true; + m_finalPt = finalPt; + m_isFinalChanged = true; + + m_requestCancel = true; + } } void OsrmRouter::CalculateRoute(m2::PointD const & startPt, ReadyCallback const & callback) { - GetPlatform().RunAsync(bind(&OsrmRouter::CalculateRouteAsync, this, startPt, callback)); + { + threads::MutexGuard guard(m_paramsMutex); + UNUSED_VALUE(guard); + + m_startPt = startPt; + + m_requestCancel = true; + } + + GetPlatform().RunAsync(bind(&OsrmRouter::CalculateRouteAsync, this, callback)); } -void OsrmRouter::CalculateRouteAsync(m2::PointD const & startPt, ReadyCallback const & callback) +void OsrmRouter::CalculateRouteAsync(ReadyCallback const & callback) { if (m_isReadyThread.test_and_set()) return; @@ -206,16 +221,19 @@ void OsrmRouter::CalculateRouteAsync(m2::PointD const & startPt, ReadyCallback c m_isReadyThread.clear(); - m2::PointD finalPt; + m2::PointD startPt, finalPt; { threads::MutexGuard params(m_paramsMutex); UNUSED_VALUE(params); + startPt = m_startPt; finalPt = m_finalPt; if (m_isFinalChanged) m_cachedFinalNodes.clear(); m_isFinalChanged = false; + + m_requestCancel = false; } try @@ -251,9 +269,9 @@ void OsrmRouter::CalculateRouteAsync(m2::PointD const & startPt, ReadyCallback c m_container.Close(); } - } - GetPlatform().RunOnGuiThread(bind(callback, route, code)); + GetPlatform().RunOnGuiThread(bind(callback, route, code)); + } } namespace @@ -314,6 +332,9 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt uint32_t mwmId = -1; ResultCode const code = FindPhantomNodes(fName, startPt, finalPt, graphNodes, MAX_NODE_CANDIDATES, mwmId); + if (m_requestCancel) + return Cancelled; + m_mapping.Unmap(); if (code != NoError) @@ -331,6 +352,9 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt size_t ni = 0, nj = 0; while (ni < MAX_NODE_CANDIDATES && nj < MAX_NODE_CANDIDATES) { + if (m_requestCancel) + break; + PhantomNodes nodes; nodes.source_phantom = graphNodes[ni].m_node; nodes.target_phantom = graphNodes[nj + MAX_NODE_CANDIDATES].m_node; @@ -365,6 +389,9 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt if (!IsRouteExist(rawRoute)) return RouteNotFound; + if (m_requestCancel) + return Cancelled; + // 5. Restore route. m_mapping.Map(m_container); @@ -385,6 +412,9 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt vector points; for (auto i : osrm::irange(0, rawRoute.unpacked_path_segments.size())) { + if (m_requestCancel) + return Cancelled; + // Get all the coordinates for the computed route size_t const n = rawRoute.unpacked_path_segments[i].size(); for (size_t j = 0; j < n; ++j) @@ -482,7 +512,7 @@ IRouter::ResultCode OsrmRouter::FindPhantomNodes(string const & fName, m2::Point return EndPointNotFound; } - getter.MakeResult(res, maxCount, mwmId, !hasFinalCache); + getter.MakeResult(res, maxCount, mwmId, !hasFinalCache, m_requestCancel); if (hasFinalCache) copy(m_cachedFinalNodes.begin(), m_cachedFinalNodes.end(), res.begin() + maxCount); else diff --git a/routing/osrm_router.hpp b/routing/osrm_router.hpp index e2a41d74cf..5168f8c510 100644 --- a/routing/osrm_router.hpp +++ b/routing/osrm_router.hpp @@ -20,8 +20,6 @@ namespace routing class OsrmRouter : public IRouter { - m2::PointD m_finalPt; - typedef function CountryFileFnT; CountryFileFnT m_countryFn; @@ -47,7 +45,7 @@ protected: bool NeedReload(string const & fPath) const; - void CalculateRouteAsync(m2::PointD const & startPt, ReadyCallback const & callback); + void CalculateRouteAsync(ReadyCallback const & callback); ResultCode CalculateRouteImpl(m2::PointD const & startPt, m2::PointD const & finalPt, Route & route); private: @@ -60,11 +58,14 @@ private: FilesMappingContainer m_container; bool m_isFinalChanged; + m2::PointD m_startPt, m_finalPt; FeatureGraphNodeVecT m_cachedFinalNodes; threads::Mutex m_paramsMutex; threads::Mutex m_routeMutex; atomic_flag m_isReadyThread; + + volatile bool m_requestCancel; }; } diff --git a/routing/router.hpp b/routing/router.hpp index 9a457bf555..43a57d1899 100644 --- a/routing/router.hpp +++ b/routing/router.hpp @@ -17,6 +17,7 @@ public: enum ResultCode { NoError = 0, + Cancelled, InconsistentMWMandRoute, StartPointNotFound, EndPointNotFound,