Use atomic<bool> primitive for thread's shared flags.

This commit is contained in:
vng 2012-09-11 16:12:47 +03:00 committed by Alex Zolotarev
parent f07420ecf2
commit fd1bc3cb18
4 changed files with 68 additions and 47 deletions

View file

@ -186,26 +186,26 @@ void Engine::SetViewportAsync(m2::RectD const & viewport, m2::RectD const & near
void Engine::SearchAsync()
{
// Avoid many threads waiting in search mutex. One is enough.
bool expected = false;
if (!m_readyThread.compare_exchange_strong(expected, true))
{
// Avoid many threads waiting in search mutex. One is enough.
threads::MutexGuard readyGuard(m_readyMutex);
if (m_readyThread)
return;
m_readyThread = true;
ASSERT ( expected, () );
return;
}
// First of all - cancel previous query.
// Order of next 4 operations is very important!
// 1. Cancel previous query.
m_pQuery->DoCancel();
// Enter to run new search.
// 2. Enter to run new search.
threads::MutexGuard searchGuard(m_searchMutex);
{
threads::MutexGuard readyGuard(m_readyMutex);
m_readyThread = false;
}
// 3. Free flag for the next search thread.
m_readyThread.store(false);
// Get current search params.
// 4. Get current search params.
SearchParams params;
m2::RectD arrRects[2];

View file

@ -11,6 +11,7 @@
#include "../std/scoped_ptr.hpp"
#include "../std/string.hpp"
#include "../std/function.hpp"
#include "../std/atomic.hpp"
class Index;
@ -61,9 +62,8 @@ private:
void SetViewportAsync(m2::RectD const & viewport, m2::RectD const & nearby);
void SearchAsync();
threads::Mutex m_searchMutex, m_updateMutex, m_readyMutex;
volatile bool m_readyThread;
threads::Mutex m_searchMutex, m_updateMutex;
volatile atomic<bool> m_readyThread;
SearchParams m_params;
m2::RectD m_viewport;

View file

@ -131,7 +131,8 @@ namespace
void Query::SetViewport(m2::RectD viewport[], size_t count)
{
ASSERT_LESS_OR_EQUAL(count, static_cast<size_t>(RECTSCOUNT), ());
// use static_cast to avoid GCC linker dummy bug
ASSERT_LESS ( count, static_cast<size_t>(RECTSCOUNT), () );
m_cancel = false;
@ -144,7 +145,8 @@ void Query::SetViewport(m2::RectD viewport[], size_t count)
void Query::SetViewportByIndex(MWMVectorT const & mwmInfo, m2::RectD const & viewport, size_t idx)
{
ASSERT_LESS_OR_EQUAL(idx, static_cast<size_t>(RECTSCOUNT), ());
// use static_cast to avoid GCC linker dummy bug
ASSERT_LESS ( idx, static_cast<size_t>(RECTSCOUNT), () );
if (viewport.IsValid())
{
@ -292,7 +294,6 @@ void Query::Search(string const & query, Results & res)
SearchAddress();
if (m_cancel) return;
LOG(LDEBUG, ("Usual search"));
SearchFeatures();
if (m_cancel) return;
@ -1335,9 +1336,10 @@ namespace
{
vector<uint32_t> const * m_offsets;
volatile bool & m_isCancelled;
volatile atomic<bool> const & m_isCancelled;
public:
FeaturesFilter(vector<uint32_t> const * offsets, volatile bool & isCancelled)
FeaturesFilter(vector<uint32_t> const * offsets,
volatile atomic<bool> const & isCancelled)
: m_offsets(offsets), m_isCancelled(isCancelled)
{
}
@ -1345,7 +1347,11 @@ namespace
bool operator() (uint32_t offset) const
{
if (m_isCancelled)
{
//LOG(LINFO, ("Throw CancelException"));
//dbg::ObjectTracker::PrintLeaks();
throw Query::CancelException();
}
return (m_offsets == 0 ||
binary_search(m_offsets->begin(), m_offsets->end(), offset));
@ -1362,7 +1368,11 @@ namespace
TrieValuesHolder(FilterT const & filter) : m_filter(filter) {}
void Resize(size_t count) { m_holder.resize(count); }
void StartNew(size_t ind) { m_ind = ind; }
void StartNew(size_t ind)
{
ASSERT_LESS ( ind, m_holder.size(), () );
m_ind = ind;
}
void operator() (Query::TrieValueT const & v)
{
if (m_filter(v.m_featureId))
@ -1390,6 +1400,38 @@ void Query::SearchFeatures(Params const & params, MWMVectorT const & mwmInfo, in
}
}
namespace
{
void FillCategories(Query::Params const & params, TrieIterator const * pTrieRoot,
TrieValuesHolder<FeaturesFilter> & categoriesHolder)
{
scoped_ptr<TrieIterator> pCategoriesRoot;
typedef TrieIterator::Edge::EdgeStrT EdgeT;
EdgeT categoriesEdge;
size_t const count = pTrieRoot->m_edge.size();
for (size_t i = 0; i < count; ++i)
{
EdgeT const & edge = pTrieRoot->m_edge[i].m_str;
ASSERT_GREATER_OR_EQUAL(edge.size(), 1, ());
if (edge[0] == search::CATEGORIES_LANG)
{
categoriesEdge = edge;
pCategoriesRoot.reset(pTrieRoot->GoToEdge(i));
break;
}
}
ASSERT_NOT_EQUAL(pCategoriesRoot, 0, ());
GetFeaturesInTrie(params.m_tokens, params.m_prefixTokens,
TrieRootPrefix(*pCategoriesRoot, categoriesEdge),
categoriesHolder);
}
}
void Query::SearchInMWM(Index::MwmLock const & mwmLock, Params const & params, int ind/* = -1*/)
{
if (MwmValue * pMwm = mwmLock.GetValue())
@ -1416,33 +1458,11 @@ void Query::SearchInMWM(Index::MwmLock const & mwmLock, Params const & params, i
// Get categories for each token separately - find needed edge with categories.
TrieValuesHolder<FeaturesFilter> categoriesHolder(filter);
size_t const count = pTrieRoot->m_edge.size();
{
scoped_ptr<TrieIterator> pCategoriesRoot;
TrieIterator::Edge::EdgeStrT categoriesEdge;
for (size_t i = 0; i < count; ++i)
{
TrieIterator::Edge::EdgeStrT const & edge = pTrieRoot->m_edge[i].m_str;
ASSERT_GREATER_OR_EQUAL(edge.size(), 1, ());
if (edge[0] == search::CATEGORIES_LANG)
{
categoriesEdge = edge;
pCategoriesRoot.reset(pTrieRoot->GoToEdge(i));
break;
}
}
ASSERT_NOT_EQUAL(pCategoriesRoot, 0, ());
GetFeaturesInTrie(params.m_tokens, params.m_prefixTokens,
TrieRootPrefix(*pCategoriesRoot, categoriesEdge),
categoriesHolder);
}
impl::FeatureLoader emitter(*this, mwmId, ind);
FillCategories(params, pTrieRoot.get(), categoriesHolder);
// Match tokens to feature for each language - iterate through first edges.
impl::FeatureLoader emitter(*this, mwmId, ind);
size_t const count = pTrieRoot->m_edge.size();
for (size_t i = 0; i < count; ++i)
{
TrieIterator::Edge::EdgeStrT const & edge = pTrieRoot->m_edge[i].m_str;

View file

@ -16,6 +16,7 @@
#include "../std/string.hpp"
#include "../std/unordered_set.hpp"
#include "../std/vector.hpp"
#include "../std/atomic.hpp"
class FeatureType;
@ -163,7 +164,7 @@ private:
StringsToSuggestVectorT const * m_pStringsToSuggest;
storage::CountryInfoGetter const * m_pInfoGetter;
volatile bool m_cancel;
volatile atomic<bool> m_cancel;
buffer_vector<strings::UniString, 32> m_tokens;
strings::UniString m_prefix;