forked from organicmaps/organicmaps
[search] Multithreaded search with blocking and canceling threads.
Remove dummy updating after My Position. TODO: Make correct updating through the GUI.
This commit is contained in:
parent
491ecba905
commit
2d0396cbd7
6 changed files with 55 additions and 70 deletions
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<search::Query> m_pQuery;
|
||||
|
|
|
@ -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<uint32_t> const & m_offsets;
|
||||
bool m_alwaysTrue;
|
||||
|
||||
volatile bool & m_isCancel;
|
||||
public:
|
||||
FeaturesFilter(vector<uint32_t> const & offsets, bool alwaysTrue)
|
||||
: m_offsets(offsets), m_alwaysTrue(alwaysTrue)
|
||||
FeaturesFilter(vector<uint32_t> 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<vector<strings::UniString> > 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<int8_t>(edge[0])),
|
||||
|
|
|
@ -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<strings::UniString, 32> m_tokens;
|
||||
|
|
Loading…
Add table
Reference in a new issue