From ef806cf18a33fd6be59ebf1dda4772637237e5c8 Mon Sep 17 00:00:00 2001 From: mvglasow Date: Thu, 28 Aug 2025 21:10:42 +0300 Subject: [PATCH] Synchronize map updates with traffic manager Signed-off-by: mvglasow --- map/framework.cpp | 14 ++++---- map/traffic_manager.cpp | 78 +++++++++++++++++++---------------------- map/traffic_manager.hpp | 16 +++++++++ 3 files changed, 60 insertions(+), 48 deletions(-) diff --git a/map/framework.cpp b/map/framework.cpp index 3ae4a917b..a3b37c201 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -443,13 +443,13 @@ void Framework::OnCountryFileDownloaded(storage::CountryId const &, m2::RectD rect = mercator::Bounds::FullRect(); if (localFile && localFile->OnDisk(MapFileType::Map)) - { - auto const res = RegisterMap(*localFile); - MwmSet::MwmId const & id = res.first; - if (id.IsAlive()) - rect = id.GetInfo()->m_bordersRect; - m_trafficManager.Invalidate(id); - } + m_trafficManager.RunSynchronized([this, localFile, &rect](){ + auto const res = RegisterMap(*localFile); + MwmSet::MwmId const & id = res.first; + if (id.IsAlive()) + rect = id.GetInfo()->m_bordersRect; + m_trafficManager.Invalidate(id); + }); m_transitManager.Invalidate(); m_isolinesManager.Invalidate(); diff --git a/map/traffic_manager.cpp b/map/traffic_manager.cpp index f365967bd..d3214d83c 100644 --- a/map/traffic_manager.cpp +++ b/map/traffic_manager.cpp @@ -301,53 +301,49 @@ void TrafficManager::Invalidate(MwmSet::MwmId const & mwmId) auto const mwmRect = mwmId.GetInfo()->m_bordersRect; // m2::RectD traffxml::TraffFeed invalidated; + for (auto it = m_messageCache.begin(); it != m_messageCache.end(); ) { - std::lock_guard lock(m_mutex); - - for (auto it = m_messageCache.begin(); it != m_messageCache.end(); ) + if (!it->second.m_location) { - if (!it->second.m_location) - { - it++; - continue; - } - - bool isInvalid = false; - - // invalidate if decoded location uses a previous version of the MWM - for (auto const & [decodedMwmId, coloring] : it->second.m_decoded) - if (decodedMwmId.GetInfo()->GetCountryName() == mwmId.GetInfo()->GetCountryName()) - isInvalid = true; - - // invalidate if bounding rect of reference points intersects with bounding rect of MWM - if (!isInvalid) - { - m2::RectD locationRect; - for (auto const & point : {it->second.m_location.value().m_from, - it->second.m_location.value().m_via, - it->second.m_location.value().m_at, - it->second.m_location.value().m_to}) - if (point) - locationRect.Add(mercator::FromLatLon(point.value().m_coordinates)); - isInvalid = locationRect.IsIntersect(mwmRect); - } - - if (isInvalid) - { - traffxml::TraffMessage message(it->second); - message.m_decoded.clear(); - invalidated.push_back(message); - it = m_messageCache.erase(it); - } - else - ++it; + it++; + continue; } - if (!invalidated.empty()) + bool isInvalid = false; + + // invalidate if decoded location uses a previous version of the MWM + for (auto const & [decodedMwmId, coloring] : it->second.m_decoded) + if (decodedMwmId.GetInfo()->GetCountryName() == mwmId.GetInfo()->GetCountryName()) + isInvalid = true; + + // invalidate if bounding rect of reference points intersects with bounding rect of MWM + if (!isInvalid) { - m_feedQueue.insert(m_feedQueue.begin(), invalidated); - m_condition.notify_one(); + m2::RectD locationRect; + for (auto const & point : {it->second.m_location.value().m_from, + it->second.m_location.value().m_via, + it->second.m_location.value().m_at, + it->second.m_location.value().m_to}) + if (point) + locationRect.Add(mercator::FromLatLon(point.value().m_coordinates)); + isInvalid = locationRect.IsIntersect(mwmRect); } + + if (isInvalid) + { + traffxml::TraffMessage message(it->second); + message.m_decoded.clear(); + invalidated.push_back(message); + it = m_messageCache.erase(it); + } + else + ++it; + } + + if (!invalidated.empty()) + { + m_feedQueue.insert(m_feedQueue.begin(), invalidated); + m_condition.notify_one(); } } diff --git a/map/traffic_manager.hpp b/map/traffic_manager.hpp index 8c24ec2f2..82b816faf 100644 --- a/map/traffic_manager.hpp +++ b/map/traffic_manager.hpp @@ -224,6 +224,9 @@ public: * for these locations are discarded and decoded again, ensuring they are based on the new MWM. * The TraFF messages themselves remain unchanged. * + * This method must either be called from a lambda function passed to `RunSynchronized()`, + * or the caller must explicitly lock the private `m_mutex` prior to calling this method. + * * @param mwmId The newly addded MWM. */ void Invalidate(MwmSet::MwmId const & mwmId); @@ -313,6 +316,19 @@ public: */ void SetTrafficUpdateCallbackFn(TrafficUpdateCallbackFn && fn); + /** + * @brief Runs a function guarded by the traffic manager mutex. + * + * This locks `m_mutex`, then runs `f` and releases the mutex. + * + * @param f + */ + void RunSynchronized(std::function f) + { + std::lock_guard lock(m_mutex); + f(); + } + private: /**