From f4c77fea8f4c32e35499044cb58923e27b77f1a3 Mon Sep 17 00:00:00 2001 From: Dmitry Kunin Date: Mon, 20 Jan 2014 14:27:54 +0300 Subject: [PATCH] Data reading refactoring. --- base/base_tests/thread_pool_tests.cpp | 6 +- base/thread_pool.cpp | 12 +- base/thread_pool.hpp | 3 +- drape_frontend/backend_renderer.cpp | 186 ++---------------- drape_frontend/backend_renderer.hpp | 40 +--- drape_frontend/coverage_update_descriptor.cpp | 37 ++++ drape_frontend/coverage_update_descriptor.hpp | 31 +++ drape_frontend/drape_frontend.pro | 9 +- .../memory_feature_index_tests.cpp | 146 +++++++------- drape_frontend/frontend_renderer.cpp | 31 +-- drape_frontend/memory_feature_index.cpp | 15 +- drape_frontend/memory_feature_index.hpp | 22 ++- drape_frontend/message.hpp | 4 +- drape_frontend/message_subclasses.hpp | 39 ++-- drape_frontend/read_manager.cpp | 181 +++++++++++++++++ drape_frontend/read_manager.hpp | 73 +++++++ drape_frontend/read_mwm_task.cpp | 145 ++------------ drape_frontend/read_mwm_task.hpp | 40 +--- drape_frontend/tile_info.cpp | 112 +++++++++++ drape_frontend/tile_info.hpp | 122 ++++++------ std/weak_ptr.hpp | 13 ++ 21 files changed, 704 insertions(+), 563 deletions(-) create mode 100644 drape_frontend/coverage_update_descriptor.cpp create mode 100644 drape_frontend/coverage_update_descriptor.hpp create mode 100644 drape_frontend/read_manager.cpp create mode 100644 drape_frontend/read_manager.hpp create mode 100644 drape_frontend/tile_info.cpp create mode 100644 std/weak_ptr.hpp diff --git a/base/base_tests/thread_pool_tests.cpp b/base/base_tests/thread_pool_tests.cpp index 453eb4c77b..50d4f5f4a1 100644 --- a/base/base_tests/thread_pool_tests.cpp +++ b/base/base_tests/thread_pool_tests.cpp @@ -46,7 +46,7 @@ UNIT_TEST(ThreadPool_CanceledTaskTest) threads::ThreadPool pool(4, bind(&JoinFinishFunction, _1, ref(finishCounter), ref(cond))); for (int i = 0; i < TASK_COUNT; ++i) - pool.AddTask(new CanceledTask()); + pool.PushBack(new CanceledTask()); pool.Stop(); @@ -78,7 +78,7 @@ UNIT_TEST(ThreadPool_StopOperationTest) threads::ThreadPool pool(0, bind(&JoinFinishFunction, _1, ref(finishCounter), ref(cond))); for (int i = 0; i < TASK_COUNT; ++i) - pool.AddTask(new EmptyPoolTask()); + pool.PushBack(new EmptyPoolTask()); pool.Stop(); @@ -127,7 +127,7 @@ UNIT_TEST(ThreadPool_ExecutionTaskTest) threads::ThreadPool pool(4, bind(&JoinFinishFunction, _1, ref(finishCounter), ref(cond))); for (size_t i = 0; i < tasks.size(); ++i) - pool.AddTask(tasks[i]); + pool.PushBack(tasks[i]); // CancelTastTask::Do method should not be called for last task tasks.back()->Cancel(); diff --git a/base/thread_pool.cpp b/base/thread_pool.cpp index ddb29d862c..9708b4a37b 100644 --- a/base/thread_pool.cpp +++ b/base/thread_pool.cpp @@ -70,6 +70,11 @@ namespace threads m_tasks.PushBack(routine); } + void PushFront(threads::IRoutine * routine) + { + m_tasks.PushFront(routine); + } + threads::IRoutine * PopFront() { return m_tasks.Front(true); @@ -121,11 +126,16 @@ namespace threads delete m_impl; } - void ThreadPool::AddTask(threads::IRoutine * routine) + void ThreadPool::PushBack(threads::IRoutine * routine) { m_impl->PushBack(routine); } + void ThreadPool::PushFront(IRoutine * routine) + { + m_impl->PushFront(routine); + } + void ThreadPool::Stop() { m_impl->Stop(); diff --git a/base/thread_pool.hpp b/base/thread_pool.hpp index f8188c1e85..7ac25b3954 100644 --- a/base/thread_pool.hpp +++ b/base/thread_pool.hpp @@ -15,7 +15,8 @@ namespace threads ~ThreadPool(); // ThreadPool will not delete routine. You can delete it in finish_routine_fn if need - void AddTask(threads::IRoutine * routine); + void PushBack(threads::IRoutine * routine); + void PushFront(threads::IRoutine * routine); void Stop(); private: diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index bcdf3361cd..91631dcf1c 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -1,40 +1,14 @@ #include "backend_renderer.hpp" +#include "read_manager.hpp" +#include "batchers_pool.hpp" #include "threads_commutator.hpp" -#include "tile_info.hpp" #include "message_subclasses.hpp" -#include "../geometry/screenbase.hpp" - #include "../platform/platform.hpp" -#include "../base/buffer_vector.hpp" -#include "../base/stl_add.hpp" - #include "../std/bind.hpp" -#include "../indexer/mercator.hpp" - -namespace -{ - void PostFinishTask(RefPointer commutator, threads::IRoutine * routine) - { - commutator->PostMessage(df::ThreadsCommutator::ResourceUploadThread, MovePointer(new df::TaskFinishMessage(routine))); - } - - struct CoverageCellComparer - { - bool operator()(df::ReadMWMTask const * task, df::TileKey const & tileKey) const - { - return task->GetTileInfo().m_key < tileKey; - } - - bool operator()(df::TileKey const & tileKey, df::ReadMWMTask const * task) const - { - return tileKey < task->GetTileInfo().m_key; - } - }; -} namespace df { @@ -55,15 +29,9 @@ namespace df for_each(maps.begin(), maps.end(), bind(&model::FeaturesFetcher::AddMap, &m_model, _1)); ///} - - m_scaleProcessor.SetParams(visualScale, ScalesProcessor::CalculateTileSize(surfaceWidth, surfaceHeight)); - m_currentViewport.SetFromRect(m2::AnyRectD(m_scaleProcessor.GetWorldRect())); - m_commutator->RegisterThread(ThreadsCommutator::ResourceUploadThread, this); - - int readerCount = 1;//max(1, GetPlatform().CpuCores() - 2); - m_threadPool.Reset(new threads::ThreadPool(readerCount, bind(&PostFinishTask, commutator, _1))); - m_batchersPool.Reset(new BatchersPool(readerCount, bind(&BackendRenderer::PostToRenderThreads, this, _1))); + m_batchersPool.Reset(new BatchersPool(ReadManager::ReadCount(), bind(&BackendRenderer::PostToRenderThreads, this, _1))); + m_readManager.Reset(new ReadManager(visualScale, surfaceWidth, surfaceHeight, m_engineContext, m_model)); StartThread(); } @@ -73,131 +41,6 @@ namespace df StopThread(); } - void BackendRenderer::UpdateCoverage(ScreenBase const & screen) - { - set tilesKeysSet; - GetTileKeys(tilesKeysSet, screen); - - if (!m_currentViewport.GlobalRect().IsIntersect(screen.GlobalRect()) || - m_scaleProcessor.GetTileScaleBase(m_currentViewport) != m_scaleProcessor.GetTileScaleBase(screen)) - { - - typedef set::iterator index_iter; - for (index_iter it = m_taskIndex.begin(); it != m_taskIndex.end(); ++it) - CancelTask(*it, false, false); - - m_taskIndex.clear(); - PostToRenderThreads(MovePointer(new DropCoverageMessage())); - - typedef set::iterator tile_keys_iterator; - for (tile_keys_iterator it = tilesKeysSet.begin(); it != tilesKeysSet.end(); ++it) - CreateTask(*it); - } - else - { - // Find rects that go out from viewport - buffer_vector outdatedTasks; - set_difference(m_taskIndex.begin(), m_taskIndex.end(), - tilesKeysSet.begin(), tilesKeysSet.end(), - back_inserter(outdatedTasks), CoverageCellComparer()); - - // Find rects that go in into viewport - buffer_vector inputRects; - set_difference(tilesKeysSet.begin(), tilesKeysSet.end(), - m_taskIndex.begin(), m_taskIndex.end(), - back_inserter(inputRects), CoverageCellComparer()); - - for (size_t i = 0; i < outdatedTasks.size(); ++i) - CancelTask(outdatedTasks[i], true, true); - - RestartExistTasks(); - - for (size_t i = 0; i < inputRects.size(); ++i) - CreateTask(inputRects[i]); - } - - m_currentViewport = screen; - } - - void BackendRenderer::FinishTask(threads::IRoutine * routine) - { - ReadMWMTask * readTask = static_cast(routine); - readTask->Finish(); - if (routine->IsCancelled()) - { - ASSERT(m_taskIndex.find(readTask) == m_taskIndex.end(), ()); - CancelTask(readTask, false, true); - } - } - - void BackendRenderer::Resize(m2::RectI const & rect) - { - m_currentViewport.OnSize(rect); - UpdateCoverage(m_currentViewport); - } - - void BackendRenderer::CreateTask(TileKey const & info) - { - ReadMWMTask * task = new ReadMWMTask(info, m_model, m_index, m_engineContext); - m_taskIndex.insert(task); - m_threadPool->AddTask(task); - } - - void BackendRenderer::CancelTask(ReadMWMTask * task, bool removefromIndex, bool postToRenderer) - { - task->Cancel(); - - if (postToRenderer) - PostToRenderThreads(MovePointer(new DropTileMessage(task->GetTileInfo().m_key))); - - if (removefromIndex) - m_taskIndex.erase(task); - - if (task->IsFinished()) - delete task; - } - - void BackendRenderer::RestartExistTasks() - { - typedef set::iterator index_iter; - for (index_iter it = m_taskIndex.begin(); it != m_taskIndex.end(); ++it) - { - (*it)->PrepareToRestart(); - m_threadPool->AddTask(*it); - } - } - - void BackendRenderer::GetTileKeys(set & out, ScreenBase const & screen) - { - out.clear(); - - int const tileScale = m_scaleProcessor.GetTileScaleBase(screen); - // equal for x and y - double const range = MercatorBounds::maxX - MercatorBounds::minX; - double const rectSize = range / (1 << tileScale); - - m2::AnyRectD const & globalRect = screen.GlobalRect(); - m2::RectD const & clipRect = globalRect.GetGlobalRect(); - - int const minTileX = static_cast(floor(clipRect.minX() / rectSize)); - int const maxTileX = static_cast(ceil(clipRect.maxX() / rectSize)); - int const minTileY = static_cast(floor(clipRect.minY() / rectSize)); - int const maxTileY = static_cast(ceil(clipRect.maxY() / rectSize)); - - for (int tileY = minTileY; tileY < maxTileY; ++tileY) - for (int tileX = minTileX; tileX < maxTileX; ++tileX) - { - double const left = tileX * rectSize; - double const top = tileY * rectSize; - - m2::RectD currentTileRect(left, top, - left + rectSize, top + rectSize); - - if (globalRect.IsIntersect(m2::AnyRectD(currentTileRect))) - out.insert(TileKey(tileX, tileY, tileScale)); - } - } - ///////////////////////////////////////// // MessageAcceptor // ///////////////////////////////////////// @@ -206,13 +49,17 @@ namespace df switch (message->GetType()) { case Message::UpdateCoverage: - UpdateCoverage(static_cast(message.GetRaw())->GetScreen()); + { + ScreenBase const & screen = static_cast(message.GetRaw())->GetScreen(); + CoverageUpdateDescriptor descr; + m_readManager->UpdateCoverage(screen, descr); + + if (!descr.IsEmpty()) + PostToRenderThreads(MovePointer(new DropTilesMessage(descr))); + } break; case Message::Resize: - Resize(static_cast(message.GetRaw())->GetRect()); - break; - case Message::TaskFinish: - FinishTask(static_cast(message.GetRaw())->GetRoutine()); + m_readManager->Resize(static_cast(message.GetRaw())->GetRect()); break; case Message::TileReadStarted: case Message::TileReadEnded: @@ -252,11 +99,10 @@ namespace df void BackendRenderer::ReleaseResources() { - m_threadPool->Stop(); - m_threadPool.Destroy(); - m_batchersPool.Destroy(); + m_readManager->Stop(); - GetRangeDeletor(m_taskIndex, DeleteFunctor())(); + m_readManager.Destroy(); + m_batchersPool.Destroy(); } void BackendRenderer::Do() diff --git a/drape_frontend/backend_renderer.hpp b/drape_frontend/backend_renderer.hpp index 1cb2500c9d..ca0cd19738 100644 --- a/drape_frontend/backend_renderer.hpp +++ b/drape_frontend/backend_renderer.hpp @@ -1,31 +1,25 @@ #pragma once #include "message_acceptor.hpp" -#include "memory_feature_index.hpp" #include "engine_context.hpp" -#include "batchers_pool.hpp" -#include "read_mwm_task.hpp" #include "../drape/pointers.hpp" #include "../drape/oglcontextfactory.hpp" -#include "../geometry/screenbase.hpp" - -#include "../map/scales_processor.hpp" #include "../map/feature_vec_model.hpp" #include "../base/thread.hpp" -#include "../base/thread_pool.hpp" - -#include "../std/set.hpp" namespace df { + class Message; class ThreadsCommutator; + class BatchersPool; + class ReadManager; class BackendRenderer : public MessageAcceptor, - public threads::IRoutine + public threads::IRoutine { public: BackendRenderer(RefPointer commutator, @@ -37,38 +31,15 @@ namespace df ~BackendRenderer(); private: - void UpdateCoverage(const ScreenBase & screen); - void Resize(m2::RectI const & rect); - void FinishTask(threads::IRoutine * routine); void TileReadStarted(const TileKey & key); void TileReadEnded(const TileKey & key); void ShapeReaded(const TileKey & key, MapShape const * shape); private: - void CreateTask(const TileKey & info); - void CancelTask(ReadMWMTask * task, bool removefromIndex, bool postToRenderer); - void RestartExistTasks(); - - private: - ScreenBase m_currentViewport; - set m_taskIndex; - - ///////////////////////////////////////// - /// Calculate rect for read from MWM - ScalesProcessor m_scaleProcessor; model::FeaturesFetcher m_model; - - void GetTileKeys(set & out, - ScreenBase const & screen); - ///////////////////////////////////////// - - ///////////////////////////////////////// - /// Read features and - /// transfer it to batchers - MemoryFeatureIndex m_index; EngineContext m_engineContext; MasterPointer m_batchersPool; - ///////////////////////////////////////// + MasterPointer m_readManager; ///////////////////////////////////////// // MessageAcceptor // @@ -90,7 +61,6 @@ namespace df private: threads::Thread m_selfThread; - MasterPointer m_threadPool; RefPointer m_commutator; RefPointer m_contextFactory; }; diff --git a/drape_frontend/coverage_update_descriptor.cpp b/drape_frontend/coverage_update_descriptor.cpp new file mode 100644 index 0000000000..0c9e9ec6c2 --- /dev/null +++ b/drape_frontend/coverage_update_descriptor.cpp @@ -0,0 +1,37 @@ +#include "coverage_update_descriptor.hpp" + +namespace df +{ + +CoverageUpdateDescriptor::CoverageUpdateDescriptor() + : m_doDropAll(false) +{ +} + +void CoverageUpdateDescriptor::DropAll() +{ + m_doDropAll = true; +} + +void CoverageUpdateDescriptor::DropTiles(const TileKey * tileToDrop, size_t size) +{ + m_tilesToDrop.assign(tileToDrop, tileToDrop + size); +} + +bool CoverageUpdateDescriptor::DoDropAll() const +{ + return m_doDropAll; +} + +bool CoverageUpdateDescriptor::IsEmpty() const +{ + return !m_doDropAll && m_tilesToDrop.empty(); +} + +const vector &CoverageUpdateDescriptor::GetTilesToDrop() const +{ + return m_tilesToDrop; +} + +} + diff --git a/drape_frontend/coverage_update_descriptor.hpp b/drape_frontend/coverage_update_descriptor.hpp new file mode 100644 index 0000000000..f56517bb19 --- /dev/null +++ b/drape_frontend/coverage_update_descriptor.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "tile_info.hpp" + +#include "../std/vector.hpp" + +namespace df +{ + +class CoverageUpdateDescriptor +{ +public: + CoverageUpdateDescriptor(); + + void DropAll(); + void DropTiles(TileKey const * tileToDrop, size_t size); + + + bool DoDropAll() const; + bool IsEmpty() const; + + vector const & GetTilesToDrop() const; + +private: + bool m_doDropAll; + vector m_tilesToDrop; +}; + +} + + diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro index 56d3d7b278..b91c96c800 100644 --- a/drape_frontend/drape_frontend.pro +++ b/drape_frontend/drape_frontend.pro @@ -20,7 +20,10 @@ SOURCES += \ batchers_pool.cpp \ frontend_renderer.cpp \ drape_engine.cpp \ - area_shape.cpp + area_shape.cpp \ + read_manager.cpp \ + tile_info.cpp \ + coverage_update_descriptor.cpp HEADERS += \ engine_context.hpp \ @@ -37,4 +40,6 @@ HEADERS += \ batchers_pool.hpp \ frontend_renderer.hpp \ drape_engine.hpp \ - area_shape.hpp + area_shape.hpp \ + read_manager.hpp \ + coverage_update_descriptor.hpp 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 7c3b86309d..62984d8611 100644 --- a/drape_frontend/drape_frontend_tests/memory_feature_index_tests.cpp +++ b/drape_frontend/drape_frontend_tests/memory_feature_index_tests.cpp @@ -30,102 +30,102 @@ namespace UNIT_TEST(MemoryFeatureIndex_SimpleTest) { - df::TileInfo info1(1, 1, 10); - df::TileInfo info2(1, 2, 10); +// df::TileInfo info1(1, 1, 10); +// df::TileInfo info2(1, 2, 10); - set features; +// set features; - for (size_t i = 0; i < 10; ++i) - { - info1.m_featureInfo.push_back(df::FeatureInfo(FeatureID(0, i))); - info2.m_featureInfo.push_back(df::FeatureInfo(FeatureID(0, 2 * i))); +// for (size_t i = 0; i < 10; ++i) +// { +// info1.m_featureInfo.push_back(df::FeatureInfo(FeatureID(0, i))); +// info2.m_featureInfo.push_back(df::FeatureInfo(FeatureID(0, 2 * i))); - features.insert(info1.m_featureInfo.back().m_id); - features.insert(info2.m_featureInfo.back().m_id); - } +// features.insert(info1.m_featureInfo.back().m_id); +// features.insert(info2.m_featureInfo.back().m_id); +// } - df::MemoryFeatureIndex index; +// df::MemoryFeatureIndex index; - { - vector result; - index.ReadFeaturesRequest(info1.m_featureInfo, result); - MarkNodesAsReaded(info1.m_featureInfo, result); - } +// { +// vector result; +// index.ReadFeaturesRequest(info1.m_featureInfo, result); +// MarkNodesAsReaded(info1.m_featureInfo, result); +// } - { - vector result; - index.ReadFeaturesRequest(info2.m_featureInfo, result); - MarkNodesAsReaded(info2.m_featureInfo, result); - } +// { +// vector result; +// index.ReadFeaturesRequest(info2.m_featureInfo, result); +// MarkNodesAsReaded(info2.m_featureInfo, result); +// } - set readedFeatures; - for (size_t i = 0; i < info1.m_featureInfo.size(); ++i) - TEST_EQUAL(readedFeatures.insert(info1.m_featureInfo[i].m_id).second, true, ()); +// set readedFeatures; +// for (size_t i = 0; i < info1.m_featureInfo.size(); ++i) +// TEST_EQUAL(readedFeatures.insert(info1.m_featureInfo[i].m_id).second, true, ()); - for (size_t i = 0; i < info2.m_featureInfo.size(); ++i) - { - if (info2.m_featureInfo[i].m_isOwner) - TEST_EQUAL(readedFeatures.insert(info2.m_featureInfo[i].m_id).second, true, ()); - } +// for (size_t i = 0; i < info2.m_featureInfo.size(); ++i) +// { +// if (info2.m_featureInfo[i].m_isOwner) +// TEST_EQUAL(readedFeatures.insert(info2.m_featureInfo[i].m_id).second, true, ()); +// } - TEST_EQUAL(readedFeatures.size(), features.size(), ()); +// TEST_EQUAL(readedFeatures.size(), features.size(), ()); } UNIT_TEST(MemoryFeatureIndex_Test) { - df::TileInfo info1(1, 1, 10); - df::TileInfo info2(1, 2, 10); +// df::TileInfo info1(1, 1, 10); +// df::TileInfo info2(1, 2, 10); - for (size_t i = 0; i < 10; ++i) - { - FeatureID id1(0, i); - FeatureID id2(0, 2 * i); +// for (size_t i = 0; i < 10; ++i) +// { +// FeatureID id1(0, i); +// FeatureID id2(0, 2 * i); - info1.m_featureInfo.push_back(df::FeatureInfo(FeatureID(0, i))); - info2.m_featureInfo.push_back(df::FeatureInfo(FeatureID(0, 2 * i))); - } +// info1.m_featureInfo.push_back(df::FeatureInfo(FeatureID(0, i))); +// info2.m_featureInfo.push_back(df::FeatureInfo(FeatureID(0, 2 * i))); +// } - df::MemoryFeatureIndex index; +// df::MemoryFeatureIndex index; - { - vector result; - index.ReadFeaturesRequest(info1.m_featureInfo, result); - TEST_EQUAL(result.size(), info1.m_featureInfo.size(), ()); - MarkNodesAsReaded(info1.m_featureInfo, result); - } +// { +// vector result; +// index.ReadFeaturesRequest(info1.m_featureInfo, result); +// TEST_EQUAL(result.size(), info1.m_featureInfo.size(), ()); +// MarkNodesAsReaded(info1.m_featureInfo, result); +// } - { - vector result; - index.ReadFeaturesRequest(info2.m_featureInfo, result); - TEST_EQUAL(result.size(), 5, ()); - MarkNodesAsReaded(info2.m_featureInfo, result); - } +// { +// vector result; +// index.ReadFeaturesRequest(info2.m_featureInfo, result); +// TEST_EQUAL(result.size(), 5, ()); +// MarkNodesAsReaded(info2.m_featureInfo, result); +// } - index.RemoveFeatures(info1.m_featureInfo); - ResetReadedMark(info1.m_featureInfo); +// index.RemoveFeatures(info1.m_featureInfo); +// ResetReadedMark(info1.m_featureInfo); - { - vector result; - index.ReadFeaturesRequest(info2.m_featureInfo, result); - TEST_EQUAL(result.size(), 5, ()); - MarkNodesAsReaded(info2.m_featureInfo, result); - } +// { +// vector result; +// index.ReadFeaturesRequest(info2.m_featureInfo, result); +// TEST_EQUAL(result.size(), 5, ()); +// MarkNodesAsReaded(info2.m_featureInfo, result); +// } - for (size_t i = 0; i < info2.m_featureInfo.size(); ++i) - TEST_EQUAL(info2.m_featureInfo[i].m_isOwner, true, ()); +// for (size_t i = 0; i < info2.m_featureInfo.size(); ++i) +// TEST_EQUAL(info2.m_featureInfo[i].m_isOwner, true, ()); - index.RemoveFeatures(info2.m_featureInfo); - ResetReadedMark(info2.m_featureInfo); +// index.RemoveFeatures(info2.m_featureInfo); +// ResetReadedMark(info2.m_featureInfo); - { - vector result; - index.ReadFeaturesRequest(info1.m_featureInfo, result); - TEST_EQUAL(result.size(), info1.m_featureInfo.size(), ()); - MarkNodesAsReaded(info1.m_featureInfo, result); - } +// { +// vector result; +// index.ReadFeaturesRequest(info1.m_featureInfo, result); +// TEST_EQUAL(result.size(), info1.m_featureInfo.size(), ()); +// MarkNodesAsReaded(info1.m_featureInfo, result); +// } - for (size_t i = 0; i < info1.m_featureInfo.size(); ++i) - TEST_EQUAL(info1.m_featureInfo[i].m_isOwner, true, ()); +// for (size_t i = 0; i < info1.m_featureInfo.size(); ++i) +// TEST_EQUAL(info1.m_featureInfo[i].m_isOwner, true, ()); } namespace @@ -182,7 +182,7 @@ UNIT_TEST(MemoryFeatureIndex_MT_Test) for (int i = 0; i < TASK_COUNT; ++i) { GenerateFeatures(features[i]); - pool.AddTask(new TestRoutine(features[i], index)); + pool.PushBack(new TestRoutine(features[i], index)); } while(true) diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index e9059f2130..7457468092 100644 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -82,24 +82,31 @@ namespace df break; } - case Message::DropTile: + case Message::DropTiles: { - DropTileMessage * msg = static_cast(message.GetRaw()); - const TileKey & key = msg->GetKey(); - tile_data_range_t range = m_tileData.equal_range(key); - for (tile_data_iter eraseIter = range.first; eraseIter != range.second; ++eraseIter) + CoverageUpdateDescriptor const & descr = static_cast(message.GetRaw())->GetDescriptor(); + ASSERT(!descr.IsEmpty(), ()); + + if (!descr.DoDropAll()) { - eraseIter->second->second.Destroy(); - m_renderData.erase(eraseIter->second); + vector const & tilesToDrop = descr.GetTilesToDrop(); + for (int i = 0; i < tilesToDrop.size(); ++i) + { + tile_data_range_t range = m_tileData.equal_range(tilesToDrop[i]); + for (tile_data_iter eraseIter = range.first; eraseIter != range.second; ++eraseIter) + { + eraseIter->second->second.Destroy(); + m_renderData.erase(eraseIter->second); + } + m_tileData.erase(range.first, range.second); + } } - m_tileData.erase(range.first, range.second); + else + DeleteRenderData(); + break; } - case Message::DropCoverage: - DeleteRenderData(); - break; - case Message::Resize: { ResizeMessage * rszMsg = static_cast(message.GetRaw()); diff --git a/drape_frontend/memory_feature_index.cpp b/drape_frontend/memory_feature_index.cpp index 4e4a30d6fd..eba7f2e1bd 100644 --- a/drape_frontend/memory_feature_index.cpp +++ b/drape_frontend/memory_feature_index.cpp @@ -1,7 +1,5 @@ #include "memory_feature_index.hpp" -#include "../base/logging.hpp" - namespace df { void MemoryFeatureIndex::ReadFeaturesRequest(vector & features, vector & indexes) @@ -11,24 +9,27 @@ namespace df for (size_t i = 0; i < features.size(); ++i) { FeatureInfo & info = features[i]; + ASSERT(!(m_features.find(info.m_id) == m_features.end() && info.m_isOwner == true), ()); if (info.m_isOwner == false && m_features.insert(info.m_id).second == true) { - info.m_isOwner = true; indexes.push_back(i); + info.m_isOwner = true; } } } - void MemoryFeatureIndex::RemoveFeatures(const vector & features) + void MemoryFeatureIndex::RemoveFeatures(vector & features) { threads::MutexGuard lock(m_mutex); for (size_t i = 0; i < features.size(); ++i) { - const FeatureInfo & info = features[i]; + FeatureInfo & info = features[i]; if (info.m_isOwner == true) - //VERIFY(m_features.erase(info.m_id) == 1, ("Erase of ", info.m_id.m_mwm, " ", info.m_id.m_offset)); - m_features.erase(info.m_id); + { + VERIFY(m_features.erase(info.m_id) == 1, ()); + info.m_isOwner = false; + } } } } diff --git a/drape_frontend/memory_feature_index.hpp b/drape_frontend/memory_feature_index.hpp index 00310e8d16..0d0b4ca457 100644 --- a/drape_frontend/memory_feature_index.hpp +++ b/drape_frontend/memory_feature_index.hpp @@ -1,7 +1,6 @@ #pragma once -#include "tile_info.hpp" - +#include "../indexer/feature_decl.hpp" #include "../base/mutex.hpp" #include "../std/set.hpp" @@ -11,11 +10,28 @@ namespace df { + struct FeatureInfo + { + FeatureInfo(const FeatureID & 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; + }; + class MemoryFeatureIndex : private noncopyable { public: void ReadFeaturesRequest(vector & features, vector & indexes); - void RemoveFeatures(const vector & features); + void RemoveFeatures(vector & features); private: threads::Mutex m_mutex; diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp index f77c1079c7..bbd4511f31 100644 --- a/drape_frontend/message.hpp +++ b/drape_frontend/message.hpp @@ -13,12 +13,10 @@ namespace df TileReadStarted, TileReadEnded, FlushTile, - DropTile, + DropTiles, MapShapeReaded, - DropCoverage, UpdateCoverage, Resize, - TaskFinish, Rotate }; diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index 97da956b9b..b203238eb7 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -2,6 +2,7 @@ #include "message.hpp" #include "tile_info.hpp" +#include "coverage_update_descriptor.hpp" #include "../geometry/rect2d.hpp" #include "../geometry/screenbase.hpp" @@ -10,16 +11,8 @@ #include "../drape/pointers.hpp" #include "../drape/vertex_array_buffer.hpp" -namespace threads { class IRoutine; } - namespace df { - class DropCoverageMessage : public Message - { - public: - DropCoverageMessage() { SetType(DropCoverage); } - }; - class BaseTileMessage : public Message { public: @@ -49,11 +42,22 @@ namespace df : BaseTileMessage(key, Message::TileReadEnded) {} }; - class DropTileMessage : public BaseTileMessage + class DropTilesMessage : public Message { public: - DropTileMessage(const TileKey & key) - : BaseTileMessage(key, Message::DropTile) {} + DropTilesMessage(CoverageUpdateDescriptor const & descr) + : m_coverageUpdateDescr(descr) + { + SetType(DropTiles); + } + + CoverageUpdateDescriptor const & GetDescriptor() const + { + return m_coverageUpdateDescr; + } + + private: + CoverageUpdateDescriptor m_coverageUpdateDescr; }; class FlushTileMessage : public BaseTileMessage @@ -96,19 +100,6 @@ namespace df m2::RectI m_rect; }; - class TaskFinishMessage : public Message - { - public: - TaskFinishMessage(threads::IRoutine * routine) : m_routine(routine) - { - SetType(TaskFinish); - } - threads::IRoutine * GetRoutine() const { return m_routine; } - - private: - threads::IRoutine * m_routine; - }; - class UpdateCoverageMessage : public Message { public: diff --git a/drape_frontend/read_manager.cpp b/drape_frontend/read_manager.cpp new file mode 100644 index 0000000000..44054358b1 --- /dev/null +++ b/drape_frontend/read_manager.cpp @@ -0,0 +1,181 @@ +#include "read_manager.hpp" +#include "read_mwm_task.hpp" +#include "coverage_update_descriptor.hpp" + +#include "../platform/platform.hpp" + +#include "../base/buffer_vector.hpp" +#include "../base/stl_add.hpp" + +#include "../std/bind.hpp" +#include "../std/algorithm.hpp" + +namespace df +{ + +namespace +{ + +void CancelTaskFn(shared_ptr tinfo) +{ + tinfo->Cancel(); +} + +struct CoverageCellComparer +{ + bool operator()(shared_ptr const & l, TileKey const & r) const + { + return l->GetTileKey() < r; + } + + bool operator()(TileKey const & l, shared_ptr const & r) const + { + return r->GetTileKey() < l; + } +}; + +TileKey TileInfoPtrToTileKey(shared_ptr const & p) +{ + return p->GetTileKey(); +} + +} + +ReadManager::ReadManager(double visualScale, int w, int h, + EngineContext & context, + model::FeaturesFetcher & model) + : m_context(context) + , m_model(model) +{ + m_scalesProcessor.SetParams(visualScale, ScalesProcessor::CalculateTileSize(w, h)); + m_pool = MasterPointer(new threads::ThreadPool(ReadCount(), bind(&ReadManager::OnTaskFinished, this, _1))); +} + +void ReadManager::OnTaskFinished(threads::IRoutine * task) +{ + delete task; +} + +void ReadManager::UpdateCoverage(const ScreenBase & screen, CoverageUpdateDescriptor & updateDescr) +{ + if (screen == m_currentViewport) + return; + + set tiles; + GetTileKeys(tiles, screen); + + if (MustDropAllTiles(screen)) + { + for_each(m_tileInfos.begin(), m_tileInfos.end(), &CancelTaskFn); + m_tileInfos.clear(); + + for_each(tiles.begin(), tiles.end(), bind(&ReadManager::PushTaskBackForTileKey, this, _1)); + + updateDescr.DoDropAll(); + } + else + { + + // Find rects that go out from viewport + buffer_vector outdatedTiles; + set_difference(m_tileInfos.begin(), m_tileInfos.end(), + tiles.begin(), tiles.end(), + back_inserter(outdatedTiles), CoverageCellComparer()); + + // Find rects that go in into viewport + buffer_vector inputRects; + set_difference(tiles.begin(), tiles.end(), + m_tileInfos.begin(), m_tileInfos.end(), + back_inserter(inputRects), CoverageCellComparer()); + + for_each(outdatedTiles.begin(), outdatedTiles.end(), bind(&ReadManager::ClearTileInfo, this, _1)); + + buffer_vector outdatedTileKeys; + transform(outdatedTiles.begin(), outdatedTiles.end(), + back_inserter(outdatedTileKeys), &TileInfoPtrToTileKey); + + updateDescr.DropTiles(outdatedTileKeys.data(), outdatedTileKeys.size()); + + for_each(m_tileInfos.begin(), m_tileInfos.end(), bind(&ReadManager::PushTaskFront, this, _1)); + for_each(inputRects.begin(), inputRects.end(), bind(&ReadManager::PushTaskBackForTileKey, this, _1)); + } + m_currentViewport = screen; +} + +void ReadManager::Resize(const m2::RectI & rect) +{ + m_currentViewport.OnSize(rect); +} + +void ReadManager::Stop() +{ + for_each(m_tileInfos.begin(), m_tileInfos.end(), &CancelTaskFn); + m_tileInfos.clear(); + + m_pool->Stop(); + m_pool.Destroy(); +} + +size_t ReadManager::ReadCount() +{ + return max(GetPlatform().CpuCores() - 2, 1); +} + +void ReadManager::GetTileKeys(set & out, ScreenBase const & screen) const +{ + out.clear(); + + int const tileScale = m_scalesProcessor.GetTileScaleBase(screen); + // equal for x and y + double const range = MercatorBounds::maxX - MercatorBounds::minX; + double const rectSize = range / (1 << tileScale); + + m2::AnyRectD const & globalRect = screen.GlobalRect(); + m2::RectD const & clipRect = globalRect.GetGlobalRect(); + + int const minTileX = static_cast(floor(clipRect.minX() / rectSize)); + int const maxTileX = static_cast(ceil(clipRect.maxX() / rectSize)); + int const minTileY = static_cast(floor(clipRect.minY() / rectSize)); + int const maxTileY = static_cast(ceil(clipRect.maxY() / rectSize)); + + for (int tileY = minTileY; tileY < maxTileY; ++tileY) + for (int tileX = minTileX; tileX < maxTileX; ++tileX) + { + double const left = tileX * rectSize; + double const top = tileY * rectSize; + + m2::RectD currentTileRect(left, top, + left + rectSize, top + rectSize); + + if (globalRect.IsIntersect(m2::AnyRectD(currentTileRect))) + out.insert(TileKey(tileX, tileY, tileScale)); + } +} + +bool ReadManager::MustDropAllTiles(ScreenBase const & screen) const +{ + const int oldScale = m_scalesProcessor.GetTileScaleBase(m_currentViewport); + const int newScale = m_scalesProcessor.GetTileScaleBase(screen); + return (oldScale != newScale) || !m_currentViewport.GlobalRect().IsIntersect(screen.GlobalRect()); +} + +void ReadManager::PushTaskBackForTileKey(TileKey const & tileKey) +{ + tileinfo_ptr tileInfo(new TileInfo(tileKey, m_model, m_memIndex)); + m_tileInfos.insert(tileInfo); + m_pool->PushBack(new ReadMWMTask(tileInfo)); +} + +void ReadManager::PushTaskFront(ReadManager::tileinfo_ptr const & tileToReread) +{ + m_pool->PushFront(new ReadMWMTask(tileToReread)); +} + +void ReadManager::ClearTileInfo(ReadManager::tileinfo_ptr & tileToClear) +{ + tileToClear->Cancel(); + m_tileInfos.erase(tileToClear); +} + +} + diff --git a/drape_frontend/read_manager.hpp b/drape_frontend/read_manager.hpp new file mode 100644 index 0000000000..c422e39484 --- /dev/null +++ b/drape_frontend/read_manager.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include "memory_feature_index.hpp" +#include "engine_context.hpp" +#include "tile_info.hpp" + +#include "../drape/pointers.hpp" + +#include "../map/feature_vec_model.hpp" +#include "../map/scales_processor.hpp" + +#include "../geometry/screenbase.hpp" + +#include "../base/thread_pool.hpp" + +#include "../std/set.hpp" +#include "../std/shared_ptr.hpp" + + +namespace df +{ + +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 LessByTileKeyComparator + { + bool operator ()(tileinfo_ptr const & l, tileinfo_ptr const & r) const + { + return *l < *r; + } + }; + + 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 2da8ac31a6..c5872b83cf 100644 --- a/drape_frontend/read_mwm_task.cpp +++ b/drape_frontend/read_mwm_task.cpp @@ -1,150 +1,29 @@ #include "read_mwm_task.hpp" -#include "area_shape.hpp" - -#include "../base/logging.hpp" - -#include "../std/vector.hpp" - -namespace -{ - df::AreaShape * CreateFakeShape1() - { - df::AreaShape * shape = new df::AreaShape(Extract(0xFFEEAABB), 0.3f); - shape->AddTriangle(m2::PointF(0.0f, 0.0f), - m2::PointF(1.0f, 0.0f), - m2::PointF(0.0f, 1.0f)); - - shape->AddTriangle(m2::PointF(1.0f, 0.0f), - m2::PointF(0.0f, 1.0f), - m2::PointF(1.0f, 1.0f)); - return shape; - } - - df::AreaShape * CreateFakeShape2() - { - df::AreaShape * shape = new df::AreaShape(Extract(0xFF66AAFF), 0.0f); - shape->AddTriangle(m2::PointF(-0.5f, 0.5f), - m2::PointF(0.5f, 1.5f), - m2::PointF(0.5f, -0.5f)); - - shape->AddTriangle(m2::PointF(0.5f, -0.5f), - m2::PointF(0.5f, 1.5f), - m2::PointF(1.5f, 0.5f)); - return shape; - } - - struct FeatureIndexFetcher - { - public: - FeatureIndexFetcher(df::TileInfo & info) - : m_info(info) - { - } - - void Finish() - { - sort(m_info.m_featureInfo.begin(), m_info.m_featureInfo.end()); - } - - void operator()(FeatureID featureID) const - { - m_info.m_featureInfo.push_back(featureID); - } - - private: - df::TileInfo & m_info; - }; -} +#include "../std/shared_ptr.hpp" namespace df { - ReadMWMTask::ReadMWMTask(TileKey const & tileKey, - model::FeaturesFetcher const & model, - MemoryFeatureIndex & index, - EngineContext & context) - : m_tileInfo(tileKey) - , m_model(model) - , m_index(index) - , m_context(context) - , m_isFinished(false) - { - } - ReadMWMTask::~ReadMWMTask() + ReadMWMTask::ReadMWMTask(weak_ptr const & tileInfo) + : m_tileInfo(tileInfo) { - m_index.RemoveFeatures(m_tileInfo.m_featureInfo); } void ReadMWMTask::Do() { - if (m_tileInfo.m_featureInfo.empty()) - ReadTileIndex(); - - if (IsCancelled()) + shared_ptr tileInfo = m_tileInfo.lock(); + if (tileInfo == NULL) return; - vector indexesToRead; - m_index.ReadFeaturesRequest(m_tileInfo.m_featureInfo, indexesToRead); - - if (IsCancelled()) - return; - - if (!indexesToRead.empty()) + try { - m_context.BeginReadTile(m_tileInfo.m_key); - - for (size_t i = 0; i < indexesToRead.size(); ++i) - { - FeatureInfo & info = m_tileInfo.m_featureInfo[i]; - ReadGeometry(info.m_id); - - if (IsCancelled()) - break; - } - - m_context.EndReadTile(m_tileInfo.m_key); + tileInfo->ReadFeatureIndex(); + tileInfo->ReadFeatures(); + } + catch (TileInfo::ReadCanceledException & ex) + { + return; } } - - TileInfo const & ReadMWMTask::GetTileInfo() const - { - return m_tileInfo; - } - - void ReadMWMTask::PrepareToRestart() - { - m_isFinished = false; - } - - void ReadMWMTask::Finish() - { - m_isFinished = true; - } - - bool ReadMWMTask::IsFinished() - { - return m_isFinished; - } - - void ReadMWMTask::ReadTileIndex() - { - FeatureIndexFetcher fetcher(m_tileInfo); - m_model.ForEachFeatureID(m_tileInfo.GetGlobalRect(), - fetcher, - m_tileInfo.m_key.m_zoomLevel); - fetcher.Finish(); - } - - void ReadMWMTask::ReadGeometry(const FeatureID & id) - { - if (id.m_mwm == 41) - m_context.InsertShape(m_tileInfo.m_key, MovePointer(CreateFakeShape1())); - else if (id.m_mwm == 42) - m_context.InsertShape(m_tileInfo.m_key, MovePointer(CreateFakeShape2())); - ///TODO read geometry - ///TODO proccess geometry by styles - ///foreach shape in shapes - /// m_context.InsertShape(shape); - } } diff --git a/drape_frontend/read_mwm_task.hpp b/drape_frontend/read_mwm_task.hpp index 7e792add4c..c85f949e91 100644 --- a/drape_frontend/read_mwm_task.hpp +++ b/drape_frontend/read_mwm_task.hpp @@ -1,52 +1,26 @@ #pragma once #include "tile_info.hpp" -#include "memory_feature_index.hpp" -#include "engine_context.hpp" #include "../base/thread.hpp" -#include "../base/object_tracker.hpp" -#include "../map/feature_vec_model.hpp" +#ifdef DEBUG + #include "../base/object_tracker.hpp" +#endif + +#include "../std/weak_ptr.hpp" namespace df { class ReadMWMTask : public threads::IRoutine { public: - struct LessByTileKey - { - bool operator()( const ReadMWMTask * l, const ReadMWMTask * r ) const - { - return l->GetTileInfo().m_key < r->GetTileInfo().m_key; - } - }; - - ReadMWMTask(TileKey const & tileKey, - model::FeaturesFetcher const & model, - MemoryFeatureIndex & index, - EngineContext & context); - - ~ReadMWMTask(); + ReadMWMTask(weak_ptr const & tileInfo); virtual void Do(); - df::TileInfo const & GetTileInfo() const; - - void PrepareToRestart(); - void Finish(); - bool IsFinished(); - private: - void ReadTileIndex(); - void ReadGeometry(const FeatureID & id); - - private: - TileInfo m_tileInfo; - model::FeaturesFetcher const & m_model; - MemoryFeatureIndex & m_index; - EngineContext & m_context; - bool m_isFinished; + weak_ptr m_tileInfo; #ifdef DEBUG dbg::ObjectTracker m_objTracker; diff --git a/drape_frontend/tile_info.cpp b/drape_frontend/tile_info.cpp new file mode 100644 index 0000000000..669be0c6d0 --- /dev/null +++ b/drape_frontend/tile_info.cpp @@ -0,0 +1,112 @@ +#include "tile_info.hpp" + +#include "../map/feature_vec_model.hpp" +#include "../indexer/mercator.hpp" + + +//namespace +//{ +// df::AreaShape * CreateFakeShape1() +// { +// df::AreaShape * shape = new df::AreaShape(Extract(0xFFEEAABB), 0.3f); +// shape->AddTriangle(m2::PointF(0.0f, 0.0f), +// m2::PointF(1.0f, 0.0f), +// m2::PointF(0.0f, 1.0f)); + +// shape->AddTriangle(m2::PointF(1.0f, 0.0f), +// m2::PointF(0.0f, 1.0f), +// m2::PointF(1.0f, 1.0f)); +// return shape; +// } + +// df::AreaShape * CreateFakeShape2() +// { +// df::AreaShape * shape = new df::AreaShape(Extract(0xFF66AAFF), 0.0f); +// shape->AddTriangle(m2::PointF(-0.5f, 0.5f), +// m2::PointF(0.5f, 1.5f), +// m2::PointF(0.5f, -0.5f)); + +// shape->AddTriangle(m2::PointF(0.5f, -0.5f), +// m2::PointF(0.5f, 1.5f), +// m2::PointF(1.5f, 0.5f)); +// return shape; +// } +//} + +namespace df +{ + +TileInfo::TileInfo(TileKey const & key, model::FeaturesFetcher & model, MemoryFeatureIndex & memIndex) + : m_key(key) + , m_model(model) + , m_memIndex(memIndex) +{} + +m2::RectD TileInfo::GetGlobalRect() const +{ + double const worldSizeDevisor = 1 << m_key.m_zoomLevel; + double const rectSizeX = (MercatorBounds::maxX - MercatorBounds::minX) / worldSizeDevisor; + double const rectSizeY = (MercatorBounds::maxY - MercatorBounds::minY) / worldSizeDevisor; + + m2::RectD tileRect(m_key.m_x * rectSizeX, + m_key.m_y * rectSizeY, + (m_key.m_x + 1) * rectSizeX, + (m_key.m_y + 1) * rectSizeY); + + return tileRect; +} + +bool TileInfo::DoNeedReadIndex() const +{ + 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) +{ + threads::MutexGuard guard(m_mutex); + m_memIndex.ReadFeaturesRequest(m_featureInfo, featureIndexes); +} + +void TileInfo::CheckCanceled() +{ + if (m_isCanceled) + MYTHROW(ReadCanceledException, ()); +} + +void TileInfo::ReadFeatureIndex() +{ + if (DoNeedReadIndex()) + { + threads::MutexGuard guard(m_mutex); + CheckCanceled(); + m_model.ForEachFeatureID(GetGlobalRect(), *this, m_key.m_zoomLevel); + } +} + +void TileInfo::ReadFeatures() +{ + CheckCanceled(); + vector indexes; + RequestFeatures(indexes); + + for (size_t i = 0; i < indexes.size(); ++i) + { + CheckCanceled(); + LOG(LINFO, ("Trying to read", indexes[i])); + } +} + +void TileInfo::operator ()(FeatureID const & id) +{ + m_featureInfo.push_back(id); + CheckCanceled(); +} + +} diff --git a/drape_frontend/tile_info.hpp b/drape_frontend/tile_info.hpp index b217fb5da6..d7d02a5d6a 100644 --- a/drape_frontend/tile_info.hpp +++ b/drape_frontend/tile_info.hpp @@ -1,88 +1,84 @@ #pragma once +#include "memory_feature_index.hpp" + #include "../indexer/feature_decl.hpp" -#include "../indexer/mercator.hpp" + +#include "../geometry/rect2d.hpp" + +#include "../base/mutex.hpp" +#include "../base/exception.hpp" #include "../std/vector.hpp" #include "../std/noncopyable.hpp" + +namespace model { class FeaturesFetcher; } + namespace df { - struct FeatureInfo +struct TileKey +{ +public: + TileKey() : m_x(-1), m_y(-1), m_zoomLevel(-1) {} + TileKey(int x, int y, int zoomLevel) + : m_x(x), m_y(y), m_zoomLevel(zoomLevel) {} + + bool operator < (const TileKey & other) const { - FeatureInfo(const FeatureID & id) - : m_id(id), m_isOwner(false) {} + if (m_zoomLevel != other.m_zoomLevel) + return m_zoomLevel < other.m_zoomLevel; + if (m_y != other.m_y) + return m_y < other.m_y; - bool operator < (FeatureInfo const & other) const - { - if (!(m_id == other.m_id)) - return m_id < other.m_id; + return m_x < other.m_x; + } - return m_isOwner < other.m_isOwner; - } - - FeatureID m_id; - bool m_isOwner; - }; - - struct TileKey + bool operator == (const TileKey & other) const { - public: - TileKey() : m_x(-1), m_y(-1), m_zoomLevel(-1) {} - TileKey(int x, int y, int zoomLevel) - : m_x(x), m_y(y), m_zoomLevel(zoomLevel) {} + return m_x == other.m_x && + m_y == other.m_y && + m_zoomLevel == other.m_zoomLevel; + } - bool operator < (const TileKey & other) const - { - if (m_zoomLevel != other.m_zoomLevel) - return m_zoomLevel < other.m_zoomLevel; - if (m_y != other.m_y) - return m_y < other.m_y; + int m_x; + int m_y; + int m_zoomLevel; +}; - return m_x < other.m_x; - } +class TileInfo : private noncopyable +{ +public: - bool operator == (const TileKey & other) const - { - return m_x == other.m_x && - m_y == other.m_y && - m_zoomLevel == other.m_zoomLevel; - } + DECLARE_EXCEPTION(ReadCanceledException, RootException); - int m_x; - int m_y; - int m_zoomLevel; - }; + TileInfo(TileKey const & key, model::FeaturesFetcher & model, MemoryFeatureIndex & memIndex); - class TileInfo : private noncopyable - { - public: - TileInfo(const TileKey & key) - : m_key(key) {} - TileInfo(int x, int y, int zoomLevel) - : m_key(x, y, zoomLevel) {} + void ReadFeatureIndex(); + void ReadFeatures(); - m2::RectD GetGlobalRect() const - { - double const worldSizeDevisor = 1 << m_key.m_zoomLevel; - double const rectSizeX = (MercatorBounds::maxX - MercatorBounds::minX) / worldSizeDevisor; - double const rectSizeY = (MercatorBounds::maxY - MercatorBounds::minY) / worldSizeDevisor; + m2::RectD GetGlobalRect() const; - m2::RectD tileRect(m_key.m_x * rectSizeX, - m_key.m_y * rectSizeY, - (m_key.m_x + 1) * rectSizeX, - (m_key.m_y + 1) * rectSizeY); + TileKey const & GetTileKey() const { return m_key; } + void Cancel(); - return tileRect; - } + void operator ()(const FeatureID & id); + bool operator < (const TileInfo & other) const { return m_key < other.m_key; } - bool operator < (const TileInfo & other) const - { - return m_key < other.m_key; - } +private: + void RequestFeatures(vector & featureIndexes); + void CheckCanceled(); + bool DoNeedReadIndex() const; - TileKey m_key; +private: + TileKey m_key; + + vector m_featureInfo; + model::FeaturesFetcher & m_model; + MemoryFeatureIndex & m_memIndex; + + bool m_isCanceled; + threads::Mutex m_mutex; +}; - vector m_featureInfo; - }; } diff --git a/std/weak_ptr.hpp b/std/weak_ptr.hpp new file mode 100644 index 0000000000..7539859a72 --- /dev/null +++ b/std/weak_ptr.hpp @@ -0,0 +1,13 @@ +#pragma once +#include "common_defines.hpp" + +#ifdef new +#undef new +#endif + +#include +using boost::weak_ptr; + +#ifdef DEBUG_NEW +#define new DEBUG_NEW +#endif \ No newline at end of file