diff --git a/drape_frontend/read_manager.cpp b/drape_frontend/read_manager.cpp index 2fb9cd5677..5eb84d879b 100644 --- a/drape_frontend/read_manager.cpp +++ b/drape_frontend/read_manager.cpp @@ -12,15 +12,8 @@ namespace df { - namespace { - -void CancelTaskFn(shared_ptr tinfo) -{ - tinfo->Cancel(); -} - struct LessCoverageCell { bool operator()(shared_ptr const & l, TileKey const & r) const @@ -38,7 +31,6 @@ TileKey TileInfoPtrToTileKey(shared_ptr const & p) { return p->GetTileKey(); } - } ReadManager::ReadManager(double visualScale, int w, int h, @@ -66,7 +58,7 @@ void ReadManager::UpdateCoverage(const ScreenBase & screen, CoverageUpdateDescri if (MustDropAllTiles(screen)) { - for_each(m_tileInfos.begin(), m_tileInfos.end(), &CancelTaskFn); + for_each(m_tileInfos.begin(), m_tileInfos.end(), bind(&ReadManager::CancelTileInfo, this, _1)); m_tileInfos.clear(); for_each(tiles.begin(), tiles.end(), bind(&ReadManager::PushTaskBackForTileKey, this, _1)); @@ -75,7 +67,6 @@ void ReadManager::UpdateCoverage(const ScreenBase & screen, CoverageUpdateDescri } else { - // Find rects that go out from viewport buffer_vector outdatedTiles; set_difference(m_tileInfos.begin(), m_tileInfos.end(), @@ -109,7 +100,7 @@ void ReadManager::Resize(const m2::RectI & rect) void ReadManager::Stop() { - for_each(m_tileInfos.begin(), m_tileInfos.end(), &CancelTaskFn); + for_each(m_tileInfos.begin(), m_tileInfos.end(), bind(&ReadManager::CancelTileInfo, this, _1)); m_tileInfos.clear(); m_pool->Stop(); @@ -161,21 +152,25 @@ bool ReadManager::MustDropAllTiles(ScreenBase const & screen) const void ReadManager::PushTaskBackForTileKey(TileKey const & tileKey) { - tileinfo_ptr tileInfo(new TileInfo(tileKey, m_model, m_memIndex)); + tileinfo_ptr tileInfo(new TileInfo(tileKey)); m_tileInfos.insert(tileInfo); - m_pool->PushBack(new ReadMWMTask(tileInfo, m_context)); + m_pool->PushBack(new ReadMWMTask(tileInfo, m_memIndex, m_model, m_context)); } -void ReadManager::PushTaskFront(ReadManager::tileinfo_ptr const & tileToReread) + void ReadManager::PushTaskFront(tileinfo_ptr const & tileToReread) { - m_pool->PushFront(new ReadMWMTask(tileToReread, m_context)); + m_pool->PushFront(new ReadMWMTask(tileToReread, m_memIndex, m_model, m_context)); } -void ReadManager::ClearTileInfo(ReadManager::tileinfo_ptr & tileToClear) + void ReadManager::CancelTileInfo(tileinfo_ptr tileToCancel) { - tileToClear->Cancel(); + tileToCancel->Cancel(m_memIndex); + } + + void ReadManager::ClearTileInfo(tileinfo_ptr & tileToClear) + { + CancelTileInfo(tileToClear); m_tileInfos.erase(tileToClear); } - } diff --git a/drape_frontend/read_manager.hpp b/drape_frontend/read_manager.hpp index 09dd9607da..d181c5ae48 100644 --- a/drape_frontend/read_manager.hpp +++ b/drape_frontend/read_manager.hpp @@ -19,55 +19,55 @@ namespace df { + class CoverageUpdateDescriptor; -class CoverageUpdateDescriptor; - -class ReadManager -{ typedef shared_ptr tileinfo_ptr; -public: - ReadManager(double visualScale, int w, int h, - EngineContext & context, - model::FeaturesFetcher & model); - void UpdateCoverage(ScreenBase const & screen, CoverageUpdateDescriptor & updateDescr); - void Resize(m2::RectI const & rect); - void Stop(); - - static size_t ReadCount(); - -private: - void OnTaskFinished(threads::IRoutine * task); - void GetTileKeys(set & out, const ScreenBase & screen) const; - bool MustDropAllTiles(ScreenBase const & screen) const; - - void PushTaskBackForTileKey(TileKey const & tileKey); - void PushTaskFront(tileinfo_ptr const & tileToReread); - -private: - - MemoryFeatureIndex m_memIndex; - EngineContext & m_context; - - model::FeaturesFetcher & m_model; - ScalesProcessor m_scalesProcessor; - - MasterPointer m_pool; - - ScreenBase m_currentViewport; - - - struct LessByTileKey + class ReadManager { - bool operator ()(tileinfo_ptr const & l, tileinfo_ptr const & r) const + public: + ReadManager(double visualScale, int w, int h, + EngineContext & context, + model::FeaturesFetcher & model); + + void UpdateCoverage(ScreenBase const & screen, CoverageUpdateDescriptor & updateDescr); + void Resize(m2::RectI const & rect); + void Stop(); + + static size_t ReadCount(); + + private: + void OnTaskFinished(threads::IRoutine * task); + void GetTileKeys(set & out, const ScreenBase & screen) const; + bool MustDropAllTiles(ScreenBase const & screen) const; + + void PushTaskBackForTileKey(TileKey const & tileKey); + void PushTaskFront(tileinfo_ptr const & tileToReread); + + private: + + MemoryFeatureIndex m_memIndex; + EngineContext & m_context; + + model::FeaturesFetcher & m_model; + ScalesProcessor m_scalesProcessor; + + MasterPointer m_pool; + + ScreenBase m_currentViewport; + + + struct LessByTileKey { - return *l < *r; - } + bool operator ()(tileinfo_ptr const & l, tileinfo_ptr const & r) const + { + return *l < *r; + } + }; + + set m_tileInfos; + + void CancelTileInfo(tileinfo_ptr tileToCancel); + void ClearTileInfo(tileinfo_ptr & tileToClear); }; - - set m_tileInfos; - - void ClearTileInfo(tileinfo_ptr & tileToClear); -}; - } diff --git a/drape_frontend/read_mwm_task.cpp b/drape_frontend/read_mwm_task.cpp index b0633245e7..3f4aed6fad 100644 --- a/drape_frontend/read_mwm_task.cpp +++ b/drape_frontend/read_mwm_task.cpp @@ -5,8 +5,13 @@ namespace df { - ReadMWMTask::ReadMWMTask(weak_ptr const & tileInfo, EngineContext & context) + ReadMWMTask::ReadMWMTask(weak_ptr const & tileInfo, + MemoryFeatureIndex & memIndex, + model::FeaturesFetcher & model, + EngineContext & context) : m_tileInfo(tileInfo) + , m_memIndex(memIndex) + , m_model(model) , m_context(context) { } @@ -19,8 +24,8 @@ namespace df try { - tileInfo->ReadFeatureIndex(); - tileInfo->ReadFeatures(m_context); + tileInfo->ReadFeatureIndex(m_model); + tileInfo->ReadFeatures(m_model, m_memIndex, m_context); } catch (TileInfo::ReadCanceledException & ex) { diff --git a/drape_frontend/read_mwm_task.hpp b/drape_frontend/read_mwm_task.hpp index 376719f03c..7888660241 100644 --- a/drape_frontend/read_mwm_task.hpp +++ b/drape_frontend/read_mwm_task.hpp @@ -17,13 +17,19 @@ namespace df class ReadMWMTask : public threads::IRoutine { public: - ReadMWMTask(weak_ptr const & tileInfo, EngineContext & context); + ReadMWMTask(weak_ptr const & tileInfo, + MemoryFeatureIndex & memIndex, + model::FeaturesFetcher & model, + EngineContext & context); virtual void Do(); private: weak_ptr m_tileInfo; + MemoryFeatureIndex & m_memIndex; + model::FeaturesFetcher & m_model; EngineContext & m_context; + #ifdef DEBUG dbg::ObjectTracker m_objTracker; #endif diff --git a/drape_frontend/tile_info.cpp b/drape_frontend/tile_info.cpp index 8faad5bb41..2b7156a30b 100644 --- a/drape_frontend/tile_info.cpp +++ b/drape_frontend/tile_info.cpp @@ -63,10 +63,8 @@ namespace namespace df { -TileInfo::TileInfo(TileKey const & key, model::FeaturesFetcher & model, MemoryFeatureIndex & memIndex) + TileInfo::TileInfo(TileKey const & key) : m_key(key) - , m_model(model) - , m_memIndex(memIndex) {} m2::RectD TileInfo::GetGlobalRect() const @@ -83,64 +81,62 @@ m2::RectD TileInfo::GetGlobalRect() const return tileRect; } -bool TileInfo::DoNeedReadIndex() const + void TileInfo::ReadFeatureIndex(model::FeaturesFetcher const & model) { - return m_featureInfo.empty(); -} - -void TileInfo::Cancel() -{ - m_isCanceled = true; - threads::MutexGuard guard(m_mutex); - m_memIndex.RemoveFeatures(m_featureInfo); -} - -void TileInfo::RequestFeatures(vector & featureIndexes) + if (DoNeedReadIndex()) { threads::MutexGuard guard(m_mutex); - m_memIndex.ReadFeaturesRequest(m_featureInfo, featureIndexes); - + CheckCanceled(); + model.ForEachFeatureID(GetGlobalRect(), *this, m_key.m_zoomLevel); + sort(m_featureInfo.begin(), m_featureInfo.end()); + } } -void TileInfo::CheckCanceled() -{ - if (m_isCanceled) - MYTHROW(ReadCanceledException, ()); -} - -void TileInfo::ReadFeatureIndex() -{ - if (DoNeedReadIndex()) + namespace { - threads::MutexGuard guard(m_mutex); - CheckCanceled(); - m_model.ForEachFeatureID(GetGlobalRect(), *this, m_key.m_zoomLevel); - } + struct IDsAccumulator + { + IDsAccumulator(vector & ids, vector const & src) + : m_ids(ids) + , m_src(src) +{ } -void TileInfo::ReadFeatures(EngineContext & context) + void operator()(size_t index) +{ + ASSERT_LESS(index, m_src.size(), ()); + m_ids.push_back(m_src[index].m_id); +} + + vector & m_ids; + vector const & m_src; + }; +} + + void TileInfo::ReadFeatures(model::FeaturesFetcher const & model, + MemoryFeatureIndex & memIndex, + EngineContext & context) { CheckCanceled(); vector indexes; - RequestFeatures(indexes); + RequestFeatures(memIndex, indexes); - for (size_t i = 0; i < indexes.size(); ++i) - { - CheckCanceled(); - LOG(LINFO, ("Trying to read", indexes[i])); + vector featuresToRead; + for_each(indexes.begin(), indexes.end(), IDsAccumulator(featuresToRead, m_featureInfo)); + + model.ReadFeatures(*this, featuresToRead); } - if (!indexes.empty() && m_key == TileKey(0,0,3)) + void TileInfo::Cancel(MemoryFeatureIndex & memIndex) { - context.BeginReadTile(m_key); - { - context.InsertShape(m_key, MovePointer(CreateFakeShape1())); - context.InsertShape(m_key, MovePointer(CreateFakeShape2())); - context.InsertShape(m_key, MovePointer(CreateFakeLine1())); - context.InsertShape(m_key, MovePointer(CreateFakeLine2())); - } - context.EndReadTile(m_key); + m_isCanceled = true; + threads::MutexGuard guard(m_mutex); + memIndex.RemoveFeatures(m_featureInfo); } + + bool TileInfo::operator ()(FeatureType const & f) + { + return true; } void TileInfo::operator ()(FeatureID const & id) @@ -149,4 +145,22 @@ void TileInfo::operator ()(FeatureID const & id) CheckCanceled(); } + //====================================================// + + bool TileInfo::DoNeedReadIndex() const + { + return m_featureInfo.empty(); + } + + void TileInfo::RequestFeatures(MemoryFeatureIndex & memIndex, vector & featureIndexes) + { + threads::MutexGuard guard(m_mutex); + memIndex.ReadFeaturesRequest(m_featureInfo, featureIndexes); + } + + void TileInfo::CheckCanceled() + { + if (m_isCanceled) + MYTHROW(ReadCanceledException, ()); + } } diff --git a/drape_frontend/tile_info.hpp b/drape_frontend/tile_info.hpp index 89d73c6d93..f3f9373ff6 100644 --- a/drape_frontend/tile_info.hpp +++ b/drape_frontend/tile_info.hpp @@ -15,6 +15,8 @@ namespace model { class FeaturesFetcher; } +class FeatureType; + namespace df { class EngineContext; @@ -51,36 +53,33 @@ public: class TileInfo : private noncopyable { public: - DECLARE_EXCEPTION(ReadCanceledException, RootException); - TileInfo(TileKey const & key, model::FeaturesFetcher & model, MemoryFeatureIndex & memIndex); + TileInfo(TileKey const & key); - void ReadFeatureIndex(); - void ReadFeatures(EngineContext & context); + void ReadFeatureIndex(model::FeaturesFetcher const & model); + void ReadFeatures(model::FeaturesFetcher const & model, + MemoryFeatureIndex & memIndex, + EngineContext & context); + void Cancel(MemoryFeatureIndex & memIndex); m2::RectD GetGlobalRect() const; - TileKey const & GetTileKey() const { return m_key; } - void Cancel(); - void operator ()(const FeatureID & id); - bool operator < (const TileInfo & other) const { return m_key < other.m_key; } + void operator ()(FeatureID const & id); + bool operator ()(FeatureType const & f); + bool operator <(TileInfo const & other) const { return m_key < other.m_key; } private: - void RequestFeatures(vector & featureIndexes); + void RequestFeatures(MemoryFeatureIndex & memIndex, vector & featureIndexes); void CheckCanceled(); bool DoNeedReadIndex() const; private: TileKey m_key; - vector m_featureInfo; - model::FeaturesFetcher & m_model; - MemoryFeatureIndex & m_memIndex; bool m_isCanceled; threads::Mutex m_mutex; }; - } diff --git a/indexer/index.hpp b/indexer/index.hpp index 3576cffc91..69d72f12e1 100644 --- a/indexer/index.hpp +++ b/indexer/index.hpp @@ -12,6 +12,7 @@ #include "../std/vector.hpp" #include "../std/unordered_set.hpp" +#include "../std/algorithm.hpp" class MwmValue : public MwmSet::MwmValueBase @@ -223,6 +224,17 @@ public: ForEachInIntervals(implFunctor, covering::FullCover, m2::RectD::GetInfiniteRect(), scale); } + template + void ReadFeatures(F & f, vector const & features) const + { + if (features.empty()) + return; + + size_t currentIndex = 0; + while (currentIndex < features.size()) + currentIndex = ReadFeatureRange(f, features, currentIndex); + } + /// Guard for loading features from particular MWM by demand. class FeaturesLoaderGuard { @@ -241,6 +253,38 @@ public: private: + template + size_t ReadFeatureRange(F & f, vector const & features, size_t index) const + { + ASSERT_LESS(index, features.size(), ()); + size_t result = index; + MwmId id = features[index].m_mwm; + MwmLock lock(*this, id); + MwmValue * pValue = lock.GetValue(); + if (pValue) + { + FeaturesVector featureReader(pValue->m_cont, pValue->GetHeader()); + while (result < features.size() && id == features[result].m_mwm) + { + FeatureID const & featureId = features[result]; + FeatureType featureType; + + featureReader.Get(featureId.m_offset, featureType); + featureType.SetID(featureId); + + f(featureType); + ++result; + } + } + else + { + result = distance(features.begin(), + lower_bound(features.begin(), features.end(), FeatureID(id + 1, 0))); + } + + return result; + } + template void ForEachInIntervals(F & f, covering::CoveringMode mode, m2::RectD const & rect, uint32_t scale) const diff --git a/map/feature_vec_model.hpp b/map/feature_vec_model.hpp index 81c5726d48..487851e7a5 100644 --- a/map/feature_vec_model.hpp +++ b/map/feature_vec_model.hpp @@ -78,6 +78,12 @@ namespace model m_multiIndex.ForEachFeatureIDInRect(toDo, rect, scale); } + template + void ReadFeatures(ToDo & toDo, vector const & features) const + { + m_multiIndex.ReadFeatures(toDo, features); + } + //@} Index const & GetIndex() const { return m_multiIndex; } diff --git a/std/algorithm.hpp b/std/algorithm.hpp index 4fa70f4ad9..84e9c6e17f 100644 --- a/std/algorithm.hpp +++ b/std/algorithm.hpp @@ -38,6 +38,7 @@ using std::transform; using std::push_heap; using std::pop_heap; using std::sort_heap; +using std::distance; using std::remove_copy_if; #ifdef DEBUG_NEW