Fixed features distribution.

This commit is contained in:
Daria Volvenkova 2016-02-12 16:05:47 +03:00 committed by Sergey Yershov
parent 094f1b97bb
commit d3c2bb3953
7 changed files with 105 additions and 67 deletions

View file

@ -37,8 +37,20 @@ public:
virtual void Do()
{
vector<FeatureID> result;
{
df::MemoryFeatureIndex::Lock lock(m_index);
m_index.ReadFeaturesRequest(m_features, result);
}
for (size_t i = 0, count = result.size(); i < count; ++i)
SetFeatureOwner(result[i]);
}
void SetFeatureOwner(FeatureID const & feature)
{
df::MemoryFeatureIndex::Lock lock(m_index);
m_index.ReadFeaturesRequest(m_features, result);
if (!m_features[feature])
m_features[feature] = m_index.SetFeatureOwner(feature);
}
private:
@ -50,7 +62,7 @@ void GenerateFeatures(df::TFeaturesInfo & features, int taskIndex)
{
int const kCount = 10000;
for (int i = 0; i < kCount; ++i)
features.push_back(df::FeatureInfo(FeatureID(MwmSet::MwmId(), taskIndex * kCount / 2 + i)));
features.insert(make_pair(FeatureID(MwmSet::MwmId(), taskIndex * kCount / 2 + i), false));
}
} // namespace
@ -89,11 +101,11 @@ UNIT_TEST(MemoryFeatureIndex_MT_Test)
for (int i = 0; i < TASK_COUNT; ++i)
{
for (size_t j = 0; j < features[i].size(); ++j)
for (auto it = features[i].begin(); it != features[i].end(); ++it)
{
allFeatures.insert(features[i][j].m_id);
if (features[i][j].m_isOwner == true)
TEST_EQUAL(readedFeatures.insert(features[i][j].m_id).second, true, ());
allFeatures.insert(it->first);
if (it->second == true)
TEST_EQUAL(readedFeatures.insert(it->first).second, true, ());
}
}

View file

@ -3,31 +3,34 @@
namespace df
{
void MemoryFeatureIndex::ReadFeaturesRequest(TFeaturesInfo & features, vector<FeatureID> & featuresToRead)
void MemoryFeatureIndex::ReadFeaturesRequest(TFeaturesInfo const & features, vector<FeatureID> & featuresToRead)
{
ASSERT(m_isLocked, ());
for (FeatureInfo & info : features)
for (auto const & featureInfo : features)
{
ASSERT(m_features.find(info.m_id) != m_features.end() || !info.m_isOwner,());
if (!info.m_isOwner && m_features.insert(info.m_id).second)
{
featuresToRead.push_back(info.m_id);
info.m_isOwner = true;
}
if (m_features.find(featureInfo.first) == m_features.end())
featuresToRead.push_back(featureInfo.first);
}
}
bool MemoryFeatureIndex::SetFeatureOwner(FeatureID const & feature)
{
ASSERT(m_isLocked, ());
return m_features.insert(feature).second;
}
void MemoryFeatureIndex::RemoveFeatures(TFeaturesInfo & features)
{
ASSERT(m_isLocked, ());
for (FeatureInfo & info : features)
for (auto & featureInfo : features)
{
if (info.m_isOwner)
if (featureInfo.second)
{
VERIFY(m_features.erase(info.m_id) == 1, ());
info.m_isOwner = false;
VERIFY(m_features.erase(featureInfo.first) == 1, ());
featureInfo.second = false;
}
}
}

View file

@ -13,30 +13,7 @@
namespace df
{
struct FeatureInfo
{
FeatureInfo()
: m_isOwner(false) {}
FeatureInfo(FeatureID const & id)
: m_id(id), m_isOwner(false) {}
bool operator < (FeatureInfo const & other) const
{
if (m_id != other.m_id)
return m_id < other.m_id;
return m_isOwner < other.m_isOwner;
}
FeatureID m_id;
bool m_isOwner;
};
// It is better for TileInfo to have size that is equal or slightly less
// than several memory pages.
size_t const kAverageFeaturesCount = 2040;
using TFeaturesInfo = buffer_vector<FeatureInfo, kAverageFeaturesCount>;
using TFeaturesInfo = map<FeatureID, bool>;
class MemoryFeatureIndex : private noncopyable
{
@ -59,7 +36,8 @@ public:
}
};
void ReadFeaturesRequest(TFeaturesInfo & features, vector<FeatureID> & featuresToRead);
void ReadFeaturesRequest(const TFeaturesInfo & features, vector<FeatureID> & featuresToRead);
bool SetFeatureOwner(const FeatureID & feature);
void RemoveFeatures(TFeaturesInfo & features);
private:

View file

@ -32,10 +32,14 @@ int const kLineSimplifyLevelEnd = 12;
RuleDrawer::RuleDrawer(TDrawerCallback const & fn,
TCheckCancelledCallback const & checkCancelled,
TSetOwnerCallback const & setOwnerFn,
TDiscardFeature const & discardFeature,
TIsCountryLoadedByNameFn const & isLoadedFn,
ref_ptr<EngineContext> context, bool is3dBuildings)
: m_callback(fn)
, m_checkCancelled(checkCancelled)
, m_setOwnerFn(setOwnerFn)
, m_discardFeatureFn(discardFeature)
, m_isLoadedFn(isLoadedFn)
, m_context(context)
, m_is3dBuidings(is3dBuildings)
@ -81,14 +85,29 @@ bool RuleDrawer::CheckCancelled()
void RuleDrawer::operator()(FeatureType const & f)
{
if (CheckCancelled())
return;
int const zoomLevel = m_context->GetTileKey().m_zoomLevel;
m2::RectD const limitRect = f.GetLimitRect(zoomLevel);
m2::RectD const tileRect = m_context->GetTileKey().GetGlobalRect();
if (!tileRect.IsIntersect(limitRect))
{
m_discardFeatureFn(f.GetID());
return;
}
if (!m_setOwnerFn(f.GetID()))
return;
Stylist s;
m_callback(f, s);
if (s.IsEmpty())
return;
int const zoomLevel = m_context->GetTileKey().m_zoomLevel;
if (s.IsCoastLine() &&
zoomLevel > scales::GetUpperWorldScale() &&
f.GetID().m_mwmId.GetInfo()->GetType() == MwmInfo::COASTS)
@ -119,14 +138,12 @@ void RuleDrawer::operator()(FeatureType const & f)
int const minVisibleScale = feature::GetMinDrawableScale(f);
m2::RectD const tileRect = m_context->GetTileKey().GetGlobalRect();
uint32_t shapesCount = 0;
auto insertShape = [this, zoomLevel, &tileRect, &shapesCount, &f](drape_ptr<MapShape> && shape)
auto insertShape = [this, zoomLevel, &tileRect, &limitRect, &shapesCount, &f](drape_ptr<MapShape> && shape)
{
int const index = static_cast<int>(shape->GetType());
ASSERT_LESS(index, m_mapShapes.size(), ());
m2::RectD const limitRect = f.GetLimitRect(zoomLevel);
if (!tileRect.IsRectInside(limitRect))
{
shape->SetFeatureInfo(dp::FeatureGeometryId(f.GetID(), shapesCount));

View file

@ -26,9 +26,12 @@ class RuleDrawer
public:
using TDrawerCallback = function<void (FeatureType const &, Stylist &)>;
using TCheckCancelledCallback = function<bool ()>;
using TSetOwnerCallback = function<bool (FeatureID const &)>;
using TDiscardFeature = function<void (FeatureID const &)>;
using TIsCountryLoadedByNameFn = function<bool (string const &)>;
RuleDrawer(TDrawerCallback const & drawerFn, TCheckCancelledCallback const & checkCancelled,
TSetOwnerCallback const & setOwnerFn, TDiscardFeature const & discardFeature,
TIsCountryLoadedByNameFn const & isLoadedFn, ref_ptr<EngineContext> context, bool is3dBuildings);
~RuleDrawer();
@ -39,6 +42,8 @@ private:
TDrawerCallback m_callback;
TCheckCancelledCallback m_checkCancelled;
TSetOwnerCallback m_setOwnerFn;
TDiscardFeature m_discardFeatureFn;
TIsCountryLoadedByNameFn m_isLoadedFn;
ref_ptr<EngineContext> m_context;

View file

@ -31,26 +31,52 @@ void TileInfo::ReadFeatureIndex(MapDataProvider const & model)
if (DoNeedReadIndex())
{
CheckCanceled();
model.ReadFeaturesID(bind(&TileInfo::ProcessID, this, _1), GetGlobalRect(), GetZoomLevel());
//sort(m_featureInfo.begin(), m_featureInfo.end());
// Do debug check instead of useless sorting.
#ifdef DEBUG
set<MwmSet::MwmId> existing;
auto i = m_featureInfo.begin();
while (i != m_featureInfo.end())
MwmSet::MwmId lastMwm;
model.ReadFeaturesID([this, &existing, &lastMwm](FeatureID const & id)
{
auto const & id = i->m_id.m_mwmId;
ASSERT(existing.insert(id).second, ());
i = find_if(i+1, m_featureInfo.end(), [&id](FeatureInfo const & info)
if (existing.empty() || lastMwm != id.m_mwmId)
{
return (id != info.m_id.m_mwmId);
});
}
ASSERT(existing.insert(id.m_mwmId).second, ());
lastMwm = id.m_mwmId;
}
#else
model.ReadFeaturesID([this](FeatureID const & id)
{
#endif
m_featureInfo.insert(make_pair(id, false));
}, GetGlobalRect(), GetZoomLevel());
}
}
void TileInfo::DiscardFeatureInfo(FeatureID const & featureId, MemoryFeatureIndex & memIndex)
{
CheckCanceled();
MemoryFeatureIndex::Lock lock(memIndex);
UNUSED_VALUE(lock);
m_featureInfo.erase(featureId);
}
bool TileInfo::SetFeatureOwner(FeatureID const & featureId, MemoryFeatureIndex & memIndex)
{
CheckCanceled();
MemoryFeatureIndex::Lock lock(memIndex);
UNUSED_VALUE(lock);
if (!m_featureInfo[featureId])
{
bool isOwner = memIndex.SetFeatureOwner(featureId);
m_featureInfo[featureId] = isOwner;
return isOwner;
}
return false;
}
void TileInfo::ReadFeatures(MapDataProvider const & model, MemoryFeatureIndex & memIndex)
{
m_context->BeginReadTile();
@ -65,14 +91,15 @@ void TileInfo::ReadFeatures(MapDataProvider const & model, MemoryFeatureIndex &
ReadFeatureIndex(model);
CheckCanceled();
featuresToRead.reserve(kAverageFeaturesCount);
memIndex.ReadFeaturesRequest(m_featureInfo, featuresToRead);
}
if (!featuresToRead.empty())
{
RuleDrawer drawer(bind(&TileInfo::InitStylist, this, _1 ,_2),
RuleDrawer drawer(bind(&TileInfo::InitStylist, this, _1, _2),
bind(&TileInfo::IsCancelled, this),
bind(&TileInfo::SetFeatureOwner, this, _1, ref(memIndex)),
bind(&TileInfo::DiscardFeatureInfo, this, _1, ref(memIndex)),
model.m_isCountryLoadedByNameFn,
make_ref(m_context), m_is3dBuildings);
model.ReadFeatures(bind<void>(ref(drawer), _1), featuresToRead);
@ -92,11 +119,6 @@ bool TileInfo::IsCancelled() const
return m_isCanceled;
}
void TileInfo::ProcessID(FeatureID const & id)
{
m_featureInfo.push_back(id);
}
void TileInfo::InitStylist(FeatureType const & f, Stylist & s)
{
CheckCanceled();

View file

@ -30,6 +30,8 @@ public:
void ReadFeatures(MapDataProvider const & model, MemoryFeatureIndex & memIndex);
void Cancel(MemoryFeatureIndex & memIndex);
bool IsCancelled() const;
bool SetFeatureOwner(FeatureID const & featureId, MemoryFeatureIndex & memIndex);
void DiscardFeatureInfo(FeatureID const & featureId, MemoryFeatureIndex & memIndex);
void Set3dBuildings(bool buildings3d) { m_is3dBuildings = buildings3d; }
bool Get3dBuildings() const { return m_is3dBuildings; }
@ -40,7 +42,6 @@ public:
private:
void ReadFeatureIndex(MapDataProvider const & model);
void ProcessID(FeatureID const & id);
void InitStylist(FeatureType const & f, Stylist & s);
void CheckCanceled() const;
bool DoNeedReadIndex() const;