diff --git a/qt/search_panel.cpp b/qt/search_panel.cpp index 921af8e189..7e36fd3191 100644 --- a/qt/search_panel.cpp +++ b/qt/search_panel.cpp @@ -12,7 +12,7 @@ namespace qt { SearchPanel::SearchPanel(DrawWidget * drawWidget, QWidget * parent) - : QWidget(parent), m_pDrawWidget(drawWidget) + : QWidget(parent), m_pDrawWidget(drawWidget), m_queryId(0) { m_pEditor = new QLineEdit(this); connect(m_pEditor, SIGNAL(textChanged(QString const &)), this, SLOT(OnSearchTextChanged(QString const &))); @@ -32,8 +32,8 @@ SearchPanel::SearchPanel(DrawWidget * drawWidget, QWidget * parent) setLayout(verticalLayout); // for multithreading support - connect(this, SIGNAL(SearchResultSignal(search::Result *)), - this, SLOT(OnSearchResult(search::Result *)), Qt::QueuedConnection); + CHECK(connect(this, SIGNAL(SearchResultSignal(search::Result *, int)), + this, SLOT(OnSearchResult(search::Result *, int)), Qt::QueuedConnection), ()); setFocusPolicy(Qt::StrongFocus); setFocusProxy(m_pEditor); @@ -51,13 +51,17 @@ SearchPanel::~SearchPanel() ClearVector(m_results); } -void SearchPanel::SearchResultThreadFunc(search::Result const & result) +void SearchPanel::SearchResultThreadFunc(search::Result const & result, int queryId) { - emit SearchResultSignal(new search::Result(result)); + if (queryId == m_queryId) + emit SearchResultSignal(new search::Result(result), queryId); } -void SearchPanel::OnSearchResult(search::Result * result) +void SearchPanel::OnSearchResult(search::Result * result, int queryId) { + if (queryId != m_queryId) + return; + if (!result->GetString().empty()) // last element { int const rowCount = m_pTable->rowCount(); @@ -77,11 +81,12 @@ void SearchPanel::OnSearchTextChanged(QString const & str) m_pTable->clear(); m_pTable->setRowCount(0); ClearVector(m_results); + ++m_queryId; QString const normalized = str.normalized(QString::NormalizationForm_KC); if (!normalized.isEmpty()) m_pDrawWidget->Search(normalized.toUtf8().constData(), - bind(&SearchPanel::SearchResultThreadFunc, this, _1)); + bind(&SearchPanel::SearchResultThreadFunc, this, _1, m_queryId)); } void SearchPanel::OnSearchPanelItemClicked(int row, int) diff --git a/qt/search_panel.hpp b/qt/search_panel.hpp index bd7ff9617f..b8107885f0 100644 --- a/qt/search_panel.hpp +++ b/qt/search_panel.hpp @@ -22,14 +22,15 @@ class SearchPanel : public QWidget /// Stores current search results vector m_results; + int volatile m_queryId; Q_OBJECT signals: - void SearchResultSignal(search::Result * result); + void SearchResultSignal(search::Result * result, int queryId); private: - void SearchResultThreadFunc(search::Result const & result); + void SearchResultThreadFunc(search::Result const & result, int queryId); public: explicit SearchPanel(DrawWidget * drawWidget, QWidget * parent); @@ -39,7 +40,7 @@ protected slots: void OnSearchPanelItemClicked(int row, int column); void OnSearchTextChanged(QString const &); /// Called via signal to support multithreading - void OnSearchResult(search::Result * result); + void OnSearchResult(search::Result * result, int queryId); }; } diff --git a/search/engine.cpp b/search/engine.cpp index e4e87dc06d..b2308883b2 100644 --- a/search/engine.cpp +++ b/search/engine.cpp @@ -1,14 +1,17 @@ #include "engine.hpp" #include "query.hpp" #include "result.hpp" +#include "../platform/concurrent_runner.hpp" #include "../indexer/feature.hpp" +#include "../std/function.hpp" #include "../std/string.hpp" #include "../std/vector.hpp" namespace search { -Engine::Engine(IndexType const * pIndex) : m_pIndex(pIndex) +Engine::Engine(IndexType const * pIndex) + : m_pIndex(pIndex), m_pRunner(new threads::ConcurrentRunner) { } @@ -16,8 +19,8 @@ void Engine::Search(string const & queryText, m2::RectD const & rect, function const & f) { - impl::Query query(queryText, rect, m_pIndex); - query.Search(f); + impl::Query * pQuery = new impl::Query(queryText, rect, m_pIndex); + m_pRunner->Run(bind(&impl::Query::SearchAndDestroy, pQuery, f)); } } // namespace search diff --git a/search/engine.hpp b/search/engine.hpp index 6da1b99020..5ff87a9a86 100644 --- a/search/engine.hpp +++ b/search/engine.hpp @@ -2,7 +2,9 @@ #include "../indexer/index.hpp" #include "../geometry/rect2d.hpp" #include "../base/base.hpp" +#include "../base/runner.hpp" #include "../std/function.hpp" +#include "../std/scoped_ptr.hpp" #include "../std/string.hpp" class FileReader; @@ -26,6 +28,7 @@ public: private: IndexType const * m_pIndex; + scoped_ptr m_pRunner; }; } // namespace search diff --git a/search/query.cpp b/search/query.cpp index 3aa6fa84ea..bb3bf882bd 100644 --- a/search/query.cpp +++ b/search/query.cpp @@ -90,7 +90,7 @@ struct FeatureProcessor } // unnamed namespace Query::Query(string const & query, m2::RectD const & viewport, IndexType const * pIndex) - : m_queryText(query), m_viewport(viewport), m_pIndex(pIndex) + : m_queryText(query), m_viewport(viewport), m_pIndex(pIndex), m_bTerminate(false) { search::Delimiters delims; SplitAndNormalizeAndSimplifyString(query, MakeBackInsertFunctor(m_keywords), delims); @@ -152,6 +152,12 @@ void Query::Search(function const & f) f(*it); } +void Query::SearchAndDestroy(function const & f) +{ + Search(f); + delete this; +} + void Query::AddResult(IntermediateResult const & result) { if (m_results.size() < 10) diff --git a/search/query.hpp b/search/query.hpp index 12a76d3267..f76932a9e4 100644 --- a/search/query.hpp +++ b/search/query.hpp @@ -26,9 +26,15 @@ public: // Search with parameters, passed in constructor. void Search(function const & f); + // Search and delete this. + void SearchAndDestroy(function const & f); + // Add result for scoring. void AddResult(IntermediateResult const & result); + // Set a flag that query is not active any more and should terminate. + void SetTerminateFlag() volatile { m_bTerminate = true; } + m2::RectD const & GetViewport() const { return m_viewport; } vector const & GetKeywords() const { return m_keywords; } strings::UniString const & GetPrefix() const { return m_prefix; } @@ -44,6 +50,8 @@ private: IndexType::Query m_indexQuery; priority_queue m_results; + + bool volatile m_bTerminate; }; } // namespace search::impl