[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:
vng 2012-02-01 17:52:53 +03:00 committed by Alex Zolotarev
parent 491ecba905
commit 2d0396cbd7
6 changed files with 55 additions and 70 deletions

View file

@ -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];

View file

@ -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);
}

View file

@ -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

View file

@ -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;

View file

@ -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])),

View file

@ -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;