diff --git a/drape_frontend/drape_frontend_tests/memory_feature_index_tests.cpp b/drape_frontend/drape_frontend_tests/memory_feature_index_tests.cpp index 71914dbf75..0e7bf31622 100644 --- a/drape_frontend/drape_frontend_tests/memory_feature_index_tests.cpp +++ b/drape_frontend/drape_frontend_tests/memory_feature_index_tests.cpp @@ -37,8 +37,20 @@ public: virtual void Do() { vector result; + { + df::MemoryFeatureIndex::Lock lock(m_index); + m_index.ReadFeaturesRequest(m_features, result); + } + + for (size_t i = 0, count = result.size(); i < count; ++i) + SetFeatureOwner(result[i]); + } + + void SetFeatureOwner(FeatureID const & feature) + { df::MemoryFeatureIndex::Lock lock(m_index); - m_index.ReadFeaturesRequest(m_features, result); + if (!m_features[feature]) + m_features[feature] = m_index.SetFeatureOwner(feature); } private: @@ -50,7 +62,7 @@ void GenerateFeatures(df::TFeaturesInfo & features, int taskIndex) { int const kCount = 10000; for (int i = 0; i < kCount; ++i) - features.push_back(df::FeatureInfo(FeatureID(MwmSet::MwmId(), taskIndex * kCount / 2 + i))); + features.insert(make_pair(FeatureID(MwmSet::MwmId(), taskIndex * kCount / 2 + i), false)); } } // namespace @@ -89,11 +101,11 @@ UNIT_TEST(MemoryFeatureIndex_MT_Test) for (int i = 0; i < TASK_COUNT; ++i) { - for (size_t j = 0; j < features[i].size(); ++j) + for (auto it = features[i].begin(); it != features[i].end(); ++it) { - allFeatures.insert(features[i][j].m_id); - if (features[i][j].m_isOwner == true) - TEST_EQUAL(readedFeatures.insert(features[i][j].m_id).second, true, ()); + allFeatures.insert(it->first); + if (it->second == true) + TEST_EQUAL(readedFeatures.insert(it->first).second, true, ()); } } diff --git a/drape_frontend/memory_feature_index.cpp b/drape_frontend/memory_feature_index.cpp index 65adb4750a..fa4e356678 100644 --- a/drape_frontend/memory_feature_index.cpp +++ b/drape_frontend/memory_feature_index.cpp @@ -3,31 +3,34 @@ namespace df { -void MemoryFeatureIndex::ReadFeaturesRequest(TFeaturesInfo & features, vector & featuresToRead) +void MemoryFeatureIndex::ReadFeaturesRequest(TFeaturesInfo const & features, vector & featuresToRead) { ASSERT(m_isLocked, ()); - for (FeatureInfo & info : features) + for (auto const & featureInfo : features) { - ASSERT(m_features.find(info.m_id) != m_features.end() || !info.m_isOwner,()); - if (!info.m_isOwner && m_features.insert(info.m_id).second) - { - featuresToRead.push_back(info.m_id); - info.m_isOwner = true; - } + if (m_features.find(featureInfo.first) == m_features.end()) + featuresToRead.push_back(featureInfo.first); } } +bool MemoryFeatureIndex::SetFeatureOwner(FeatureID const & feature) +{ + ASSERT(m_isLocked, ()); + + return m_features.insert(feature).second; +} + void MemoryFeatureIndex::RemoveFeatures(TFeaturesInfo & features) { ASSERT(m_isLocked, ()); - for (FeatureInfo & info : features) + for (auto & featureInfo : features) { - if (info.m_isOwner) + if (featureInfo.second) { - VERIFY(m_features.erase(info.m_id) == 1, ()); - info.m_isOwner = false; + VERIFY(m_features.erase(featureInfo.first) == 1, ()); + featureInfo.second = false; } } } diff --git a/drape_frontend/memory_feature_index.hpp b/drape_frontend/memory_feature_index.hpp index 6d70dee9e5..fa103f3ce6 100644 --- a/drape_frontend/memory_feature_index.hpp +++ b/drape_frontend/memory_feature_index.hpp @@ -13,30 +13,7 @@ namespace df { -struct FeatureInfo -{ - FeatureInfo() - : m_isOwner(false) {} - - FeatureInfo(FeatureID const & id) - : m_id(id), m_isOwner(false) {} - - bool operator < (FeatureInfo const & other) const - { - if (m_id != other.m_id) - return m_id < other.m_id; - - return m_isOwner < other.m_isOwner; - } - - FeatureID m_id; - bool m_isOwner; -}; - -// It is better for TileInfo to have size that is equal or slightly less -// than several memory pages. -size_t const kAverageFeaturesCount = 2040; -using TFeaturesInfo = buffer_vector; +using TFeaturesInfo = map; class MemoryFeatureIndex : private noncopyable { @@ -59,7 +36,8 @@ public: } }; - void ReadFeaturesRequest(TFeaturesInfo & features, vector & featuresToRead); + void ReadFeaturesRequest(const TFeaturesInfo & features, vector & featuresToRead); + bool SetFeatureOwner(const FeatureID & feature); void RemoveFeatures(TFeaturesInfo & features); private: diff --git a/drape_frontend/rule_drawer.cpp b/drape_frontend/rule_drawer.cpp index 240a0e8232..3255c0bc74 100644 --- a/drape_frontend/rule_drawer.cpp +++ b/drape_frontend/rule_drawer.cpp @@ -32,10 +32,14 @@ int const kLineSimplifyLevelEnd = 12; RuleDrawer::RuleDrawer(TDrawerCallback const & fn, TCheckCancelledCallback const & checkCancelled, + TSetOwnerCallback const & setOwnerFn, + TDiscardFeature const & discardFeature, TIsCountryLoadedByNameFn const & isLoadedFn, ref_ptr context, bool is3dBuildings) : m_callback(fn) , m_checkCancelled(checkCancelled) + , m_setOwnerFn(setOwnerFn) + , m_discardFeatureFn(discardFeature) , m_isLoadedFn(isLoadedFn) , m_context(context) , m_is3dBuidings(is3dBuildings) @@ -81,14 +85,29 @@ bool RuleDrawer::CheckCancelled() void RuleDrawer::operator()(FeatureType const & f) { + if (CheckCancelled()) + return; + + int const zoomLevel = m_context->GetTileKey().m_zoomLevel; + + m2::RectD const limitRect = f.GetLimitRect(zoomLevel); + m2::RectD const tileRect = m_context->GetTileKey().GetGlobalRect(); + + if (!tileRect.IsIntersect(limitRect)) + { + m_discardFeatureFn(f.GetID()); + return; + } + + if (!m_setOwnerFn(f.GetID())) + return; + Stylist s; m_callback(f, s); if (s.IsEmpty()) return; - int const zoomLevel = m_context->GetTileKey().m_zoomLevel; - if (s.IsCoastLine() && zoomLevel > scales::GetUpperWorldScale() && f.GetID().m_mwmId.GetInfo()->GetType() == MwmInfo::COASTS) @@ -119,14 +138,12 @@ void RuleDrawer::operator()(FeatureType const & f) int const minVisibleScale = feature::GetMinDrawableScale(f); - m2::RectD const tileRect = m_context->GetTileKey().GetGlobalRect(); uint32_t shapesCount = 0; - auto insertShape = [this, zoomLevel, &tileRect, &shapesCount, &f](drape_ptr && shape) + auto insertShape = [this, zoomLevel, &tileRect, &limitRect, &shapesCount, &f](drape_ptr && shape) { int const index = static_cast(shape->GetType()); ASSERT_LESS(index, m_mapShapes.size(), ()); - m2::RectD const limitRect = f.GetLimitRect(zoomLevel); if (!tileRect.IsRectInside(limitRect)) { shape->SetFeatureInfo(dp::FeatureGeometryId(f.GetID(), shapesCount)); diff --git a/drape_frontend/rule_drawer.hpp b/drape_frontend/rule_drawer.hpp index 4af2842783..6bf980f237 100644 --- a/drape_frontend/rule_drawer.hpp +++ b/drape_frontend/rule_drawer.hpp @@ -26,9 +26,12 @@ class RuleDrawer public: using TDrawerCallback = function; using TCheckCancelledCallback = function; + using TSetOwnerCallback = function; + using TDiscardFeature = function; using TIsCountryLoadedByNameFn = function; RuleDrawer(TDrawerCallback const & drawerFn, TCheckCancelledCallback const & checkCancelled, + TSetOwnerCallback const & setOwnerFn, TDiscardFeature const & discardFeature, TIsCountryLoadedByNameFn const & isLoadedFn, ref_ptr context, bool is3dBuildings); ~RuleDrawer(); @@ -39,6 +42,8 @@ private: TDrawerCallback m_callback; TCheckCancelledCallback m_checkCancelled; + TSetOwnerCallback m_setOwnerFn; + TDiscardFeature m_discardFeatureFn; TIsCountryLoadedByNameFn m_isLoadedFn; ref_ptr m_context; diff --git a/drape_frontend/tile_info.cpp b/drape_frontend/tile_info.cpp index 391f616241..e2e39fb005 100644 --- a/drape_frontend/tile_info.cpp +++ b/drape_frontend/tile_info.cpp @@ -31,26 +31,52 @@ void TileInfo::ReadFeatureIndex(MapDataProvider const & model) if (DoNeedReadIndex()) { CheckCanceled(); - model.ReadFeaturesID(bind(&TileInfo::ProcessID, this, _1), GetGlobalRect(), GetZoomLevel()); - //sort(m_featureInfo.begin(), m_featureInfo.end()); - // Do debug check instead of useless sorting. #ifdef DEBUG set existing; - auto i = m_featureInfo.begin(); - while (i != m_featureInfo.end()) + MwmSet::MwmId lastMwm; + model.ReadFeaturesID([this, &existing, &lastMwm](FeatureID const & id) { - auto const & id = i->m_id.m_mwmId; - ASSERT(existing.insert(id).second, ()); - i = find_if(i+1, m_featureInfo.end(), [&id](FeatureInfo const & info) + if (existing.empty() || lastMwm != id.m_mwmId) { - return (id != info.m_id.m_mwmId); - }); - } + ASSERT(existing.insert(id.m_mwmId).second, ()); + lastMwm = id.m_mwmId; + } +#else + model.ReadFeaturesID([this](FeatureID const & id) + { #endif + m_featureInfo.insert(make_pair(id, false)); + }, GetGlobalRect(), GetZoomLevel()); } } +void TileInfo::DiscardFeatureInfo(FeatureID const & featureId, MemoryFeatureIndex & memIndex) +{ + CheckCanceled(); + + MemoryFeatureIndex::Lock lock(memIndex); + UNUSED_VALUE(lock); + + m_featureInfo.erase(featureId); +} + +bool TileInfo::SetFeatureOwner(FeatureID const & featureId, MemoryFeatureIndex & memIndex) +{ + CheckCanceled(); + + MemoryFeatureIndex::Lock lock(memIndex); + UNUSED_VALUE(lock); + + if (!m_featureInfo[featureId]) + { + bool isOwner = memIndex.SetFeatureOwner(featureId); + m_featureInfo[featureId] = isOwner; + return isOwner; + } + return false; +} + void TileInfo::ReadFeatures(MapDataProvider const & model, MemoryFeatureIndex & memIndex) { m_context->BeginReadTile(); @@ -65,14 +91,15 @@ void TileInfo::ReadFeatures(MapDataProvider const & model, MemoryFeatureIndex & ReadFeatureIndex(model); CheckCanceled(); - featuresToRead.reserve(kAverageFeaturesCount); memIndex.ReadFeaturesRequest(m_featureInfo, featuresToRead); } if (!featuresToRead.empty()) { - RuleDrawer drawer(bind(&TileInfo::InitStylist, this, _1 ,_2), + RuleDrawer drawer(bind(&TileInfo::InitStylist, this, _1, _2), bind(&TileInfo::IsCancelled, this), + bind(&TileInfo::SetFeatureOwner, this, _1, ref(memIndex)), + bind(&TileInfo::DiscardFeatureInfo, this, _1, ref(memIndex)), model.m_isCountryLoadedByNameFn, make_ref(m_context), m_is3dBuildings); model.ReadFeatures(bind(ref(drawer), _1), featuresToRead); @@ -92,11 +119,6 @@ bool TileInfo::IsCancelled() const return m_isCanceled; } -void TileInfo::ProcessID(FeatureID const & id) -{ - m_featureInfo.push_back(id); -} - void TileInfo::InitStylist(FeatureType const & f, Stylist & s) { CheckCanceled(); diff --git a/drape_frontend/tile_info.hpp b/drape_frontend/tile_info.hpp index e2166cfccb..f658479ff5 100644 --- a/drape_frontend/tile_info.hpp +++ b/drape_frontend/tile_info.hpp @@ -30,6 +30,8 @@ public: void ReadFeatures(MapDataProvider const & model, MemoryFeatureIndex & memIndex); void Cancel(MemoryFeatureIndex & memIndex); bool IsCancelled() const; + bool SetFeatureOwner(FeatureID const & featureId, MemoryFeatureIndex & memIndex); + void DiscardFeatureInfo(FeatureID const & featureId, MemoryFeatureIndex & memIndex); void Set3dBuildings(bool buildings3d) { m_is3dBuildings = buildings3d; } bool Get3dBuildings() const { return m_is3dBuildings; } @@ -40,7 +42,6 @@ public: private: void ReadFeatureIndex(MapDataProvider const & model); - void ProcessID(FeatureID const & id); void InitStylist(FeatureType const & f, Stylist & s); void CheckCanceled() const; bool DoNeedReadIndex() const;