From 2d0396cbd7dd1d5173d95efe2c002058ae33517a Mon Sep 17 00:00:00 2001 From: vng Date: Wed, 1 Feb 2012 17:52:53 +0300 Subject: [PATCH] [search] Multithreaded search with blocking and canceling threads. Remove dummy updating after My Position. TODO: Make correct updating through the GUI. --- iphone/Maps/Classes/SearchVC.mm | 2 - map/framework.cpp | 11 +---- search/search_engine.cpp | 81 +++++++++++++-------------------- search/search_engine.hpp | 11 ++--- search/search_query.cpp | 15 ++++-- search/search_query.hpp | 5 ++ 6 files changed, 55 insertions(+), 70 deletions(-) diff --git a/iphone/Maps/Classes/SearchVC.mm b/iphone/Maps/Classes/SearchVC.mm index c1dacf7e33..cba0c9d8c9 100644 --- a/iphone/Maps/Classes/SearchVC.mm +++ b/iphone/Maps/Classes/SearchVC.mm @@ -406,8 +406,6 @@ static void OnSearchResultCallback(search::Results const & res, int queryId) - (void)addResult:(id)result { - /// @todo Temporary, for test. - LOG(LINFO, ("Clear results")); m_results.clear(); search::Results const * r = [result get]; diff --git a/map/framework.cpp b/map/framework.cpp index 245af68e78..e0da2e5095 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -694,8 +694,8 @@ search::Engine * Framework::GetSearchEngine() m_pSearchEngine.reset( new search::Engine(&m_model.GetIndex(), new CategoriesHolder(*pReader), pl.GetReader(PACKED_POLYGONS_FILE), - pl.GetReader(COUNTRIES_FILE))); - m_pSearchEngine->SetPreferredLanguage(languages::CurrentLanguage()); + pl.GetReader(COUNTRIES_FILE), + languages::CurrentLanguage())); } } return m_pSearchEngine.get(); @@ -707,13 +707,6 @@ void Framework::Search(string const & text, SearchCallbackT callback) m2::RectD const viewport = m_navigator.Screen().ClipRect(); pSearchEngine->SetViewport(viewport); - -#ifdef OMIM_OS_DESKTOP - // Mobile version works with GPS notifications. - if (m_locationState.IsValidPosition()) - pSearchEngine->SetPositionSimple(m_locationState.Position()); -#endif - pSearchEngine->Search(text, callback); } diff --git a/search/search_engine.cpp b/search/search_engine.cpp index b0aadda2ec..c5bd0216f4 100644 --- a/search/search_engine.cpp +++ b/search/search_engine.cpp @@ -41,8 +41,9 @@ public: }; Engine::Engine(IndexType const * pIndex, CategoriesHolder * pCategories, - ModelReaderPtr polyR, ModelReaderPtr countryR) - : m_trackEnable(false), m_pIndex(pIndex), m_pData(new EngineData(polyR, countryR)) + ModelReaderPtr polyR, ModelReaderPtr countryR, + string const & lang) + : m_pIndex(pIndex), m_pData(new EngineData(polyR, countryR)) { if (pCategories) { @@ -54,6 +55,7 @@ Engine::Engine(IndexType const * pIndex, CategoriesHolder * pCategories, &m_pData->m_categories, &m_pData->m_stringsToSuggest, &m_pData->m_infoGetter)); + m_pQuery->SetPreferredLanguage(lang); } Engine::~Engine() @@ -90,17 +92,12 @@ void Engine::InitializeCategoriesAndSuggestStrings(CategoriesHolder const & cate void Engine::SetViewport(m2::RectD const & viewport) { - m_savedViewport = viewport; - - if (!m_trackEnable) - { - m_pQuery->SetViewport(viewport); - m_pQuery->SetPosition(viewport.Center()); - } + m_viewport = viewport; } void Engine::SetPosition(double lat, double lon) { + /* m2::PointD const oldPos = m_pQuery->GetPosition(); if (m_trackEnable && @@ -117,15 +114,12 @@ void Engine::SetPosition(double lat, double lon) RepeatSearch(); } -} - -void Engine::SetPositionSimple(m2::PointD const & pt) -{ - m_pQuery->SetPosition(pt); + */ } void Engine::EnablePositionTrack(bool enable) { + /* m_trackEnable = enable; if (m_trackEnable) @@ -141,63 +135,52 @@ void Engine::EnablePositionTrack(bool enable) RepeatSearch(); } -} - -void Engine::SetPreferredLanguage(string const & lang) -{ - m_pQuery->SetPreferredLanguage(lang); + */ } void Engine::Search(string const & query, SearchCallbackT const & callback) { { - // Update new search params. threads::MutexGuard guard(m_updateMutex); + m_query = query; m_callback = callback; - m_queryText = query; } + // bind does copy of 'query' and 'callback' GetPlatform().RunAsync(bind(&Engine::SearchAsync, this)); } void Engine::SearchAsync() { + m_pQuery->DoCancel(); + + // Enter to run new search. + threads::MutexGuard guard(m_searchMutex); + + m_pQuery->SetViewport(m_viewport); + m_pQuery->SetPosition(m_viewport.Center()); + Results res; - SearchCallbackT f; + string query; + SearchCallbackT callback; + + try { - // Enter to run new search. - threads::MutexGuard searchGuard(m_searchMutex); - { - // First - get new search params. - threads::MutexGuard updateGuard(m_updateMutex); - - if (m_queryInProgress != m_queryText) - { - m_queryInProgress = m_queryText; - f = m_callback; - } - else - { - // If search params don't changed - skip this query. - return; - } + threads::MutexGuard guard(m_updateMutex); + query = m_query; + callback = m_callback; } - LOG(LINFO, ("Call search for query: ", m_queryInProgress)); - m_pQuery->Search(m_queryInProgress, res); + m_pQuery->Search(query, res); + } + catch (Query::CancelException const &) + { + return; } - // emit results without search mutex lock - LOG(LINFO, ("Emit search results: ", res.Count())); - f(res); -} - -void Engine::RepeatSearch() -{ - if (!m_queryText.empty() && !m_callback.empty()) - Search(m_queryText, m_callback); + callback(res); } string Engine::GetCountryFile(m2::PointD const & pt) const diff --git a/search/search_engine.hpp b/search/search_engine.hpp index d4aae1451a..752d754af8 100644 --- a/search/search_engine.hpp +++ b/search/search_engine.hpp @@ -36,13 +36,12 @@ public: // Doesn't take ownership of @pIndex. Takes ownership of pCategories Engine(IndexType const * pIndex, CategoriesHolder * pCategories, - ModelReaderPtr polyR, ModelReaderPtr countryR); + ModelReaderPtr polyR, ModelReaderPtr countryR, + string const & lang); ~Engine(); void SetViewport(m2::RectD const & viewport); void SetPosition(double lat, double lon); - void SetPositionSimple(m2::PointD const & pt); - void SetPreferredLanguage(string const & lang); void EnablePositionTrack(bool enable); @@ -54,15 +53,13 @@ private: void InitializeCategoriesAndSuggestStrings(CategoriesHolder const & categories); void SearchAsync(); - void RepeatSearch(); threads::Mutex m_searchMutex, m_updateMutex; + string m_query; SearchCallbackT m_callback; - string m_queryText, m_queryInProgress; - m2::RectD m_savedViewport; - bool m_trackEnable; + m2::RectD m_viewport; Index const * m_pIndex; scoped_ptr m_pQuery; diff --git a/search/search_query.cpp b/search/search_query.cpp index 72d35d6607..12d3c774ab 100644 --- a/search/search_query.cpp +++ b/search/search_query.cpp @@ -141,6 +141,7 @@ void Query::Search(string const & query, Results & res, unsigned int resultsNeed { // Initialize. { + m_cancel = false; m_rawQuery = query; m_uniQuery = NormalizeAndSimplifyString(m_rawQuery); m_tokens.clear(); @@ -182,10 +183,13 @@ void Query::Search(string const & query, Results & res, unsigned int resultsNeed } } + if (m_cancel) return; SuggestStrings(); + if (m_cancel) return; SearchFeatures(); + if (m_cancel) return; FlushResults(res); } @@ -490,14 +494,19 @@ namespace { vector const & m_offsets; bool m_alwaysTrue; + + volatile bool & m_isCancel; public: - FeaturesFilter(vector const & offsets, bool alwaysTrue) - : m_offsets(offsets), m_alwaysTrue(alwaysTrue) + FeaturesFilter(vector const & offsets, bool alwaysTrue, volatile bool & isCancel) + : m_offsets(offsets), m_alwaysTrue(alwaysTrue), m_isCancel(isCancel) { } bool operator() (uint32_t offset) const { + if (m_isCancel) + throw Query::CancelException(); + return (m_alwaysTrue || binary_search(m_offsets.begin(), m_offsets.end(), offset)); } }; @@ -542,7 +551,7 @@ void Query::SearchFeatures(vector > const & tokens, MatchFeaturesInTrie(tokens, m_prefix, *pLangRoot, edge.size() == 1 ? NULL : &edge[1], edge.size() - 1, - FeaturesFilter(m_offsetsInViewport[mwmId], isWorld), emitter); + FeaturesFilter(m_offsetsInViewport[mwmId], isWorld, m_cancel), emitter); LOG(LDEBUG, ("Lang:", StringUtf8Multilang::GetLangByCode(static_cast(edge[0])), diff --git a/search/search_query.hpp b/search/search_query.hpp index b35c943ecd..b3cc40ae65 100644 --- a/search/search_query.hpp +++ b/search/search_query.hpp @@ -58,6 +58,9 @@ public: void ClearCache(); + inline void DoCancel() { m_cancel = true; } + struct CancelException {}; + private: friend class impl::FeatureLoader; @@ -87,6 +90,8 @@ private: storage::CountryInfoGetter const * m_pInfoGetter; int m_preferredLanguage; + volatile bool m_cancel; + string m_rawQuery; strings::UniString m_uniQuery; buffer_vector m_tokens;