Parallel implementation of Polygonizer.

This commit is contained in:
Yury Melnichek 2011-02-27 13:47:28 +01:00 committed by Alex Zolotarev
parent 1c0f5a6553
commit a482c51fbc
2 changed files with 71 additions and 21 deletions

View file

@ -308,6 +308,7 @@ bool GenerateImpl(GenerateInfo & info)
FeaturePolygonizerType bucketer(info);
TParser<FeaturePolygonizerType, holder_t> parser(bucketer, holder);
ParseXMLFromStdIn(parser);
bucketer.Finish();
info.bucketNames = bucketer.Names();
}
else

View file

@ -1,23 +1,27 @@
#pragma once
#include "../../base/base.hpp"
#include "kml_parser.hpp"
#include "world_map_generator.hpp"
#include "../../indexer/feature.hpp"
#include "../../indexer/feature_visibility.hpp"
#include "../../indexer/cell_id.hpp"
#include "../../coding/file_writer.hpp"
#include "../../geometry/rect2d.hpp"
#include "../../coding/file_writer.hpp"
#include "../../base/base.hpp"
#include "../../base/buffer_vector.hpp"
#include "../../base/macros.hpp"
#include "../../std/scoped_ptr.hpp"
#include "../../std/string.hpp"
#include <boost/scoped_ptr.hpp>
#ifndef PARALLEL_POLYGONIZER
#define PARALLEL_POLYGONIZER 1
#endif
#include "kml_parser.hpp"
#include "world_map_generator.hpp"
#if PARALLEL_POLYGONIZER
#include <QSemaphore>
#include <QThreadPool>
#include <QMutex>
#include <QMutexLocker>
#endif
namespace feature
{
@ -29,6 +33,9 @@ namespace feature
template <class TInfo>
Polygonizer(TInfo & info) : m_FeatureOutInitData(info.datFilePrefix, info.datFileSuffix),
m_worldMap(info.maxScaleForWorldFeatures, info.mergeCoastlines, m_FeatureOutInitData)
#if PARALLEL_POLYGONIZER
, m_ThreadPoolSemaphore(m_ThreadPool.maxThreadCount() * 4)
#endif
{
CHECK(kml::LoadCountriesList(info.datFilePrefix, m_countries, info.simplifyCountriesLevel),
("Error loading country polygons files"));
@ -41,6 +48,7 @@ namespace feature
}
~Polygonizer()
{
Finish();
for_each(m_Buckets.begin(), m_Buckets.end(), DeleteFunctor());
}
@ -90,22 +98,29 @@ namespace feature
EmitFeature(vec[0], fb);
else
{
for (size_t i = 0; i < vec.size(); ++i)
this->operator()(vec[i], fb);
#if PARALLEL_POLYGONIZER
m_ThreadPoolSemaphore.acquire();
m_ThreadPool.start(new PolygonizerTask(this, vec, fb));
#else
PolygonizerTask task(this, vec, fb);
task.run();
#endif
}
}
void operator() (kml::CountryPolygons const * country, FeatureBuilder1 const & fb)
void Finish()
{
PointChecker doCheck(country->m_regions);
fb.ForEachTruePointRef(doCheck);
if (doCheck.m_belongs)
EmitFeature(country, fb);
#if PARALLEL_POLYGONIZER
m_ThreadPool.waitForDone();
#endif
}
void EmitFeature(kml::CountryPolygons const * country, FeatureBuilder1 const & fb)
{
#if PARALLEL_POLYGONIZER
QMutexLocker mutexLocker(&m_EmitFeatureMutex);
UNUSED_VALUE(mutexLocker);
#endif
if (country->m_index == -1)
{
m_Names.push_back(country->m_name);
@ -126,9 +141,43 @@ namespace feature
vector<FeatureOutT*> m_Buckets;
vector<string> m_Names;
kml::CountriesContainerT m_countries;
WorldMapGenerator<FeatureOutT> m_worldMap;
#if PARALLEL_POLYGONIZER
QThreadPool m_ThreadPool;
QSemaphore m_ThreadPoolSemaphore;
QMutex m_EmitFeatureMutex;
friend class PolygonizerTask;
class PolygonizerTask : public QRunnable
{
public:
PolygonizerTask(Polygonizer * pPolygonizer,
buffer_vector<kml::CountryPolygons const *, 32> const & countries,
FeatureBuilder1 const & fb)
: m_pPolygonizer(pPolygonizer), m_Countries(countries), m_FB(fb) {}
void run()
{
for (size_t i = 0; i < m_Countries.size(); ++i)
{
PointChecker doCheck(m_Countries[i]->m_regions);
m_FB.ForEachTruePointRef(doCheck);
if (doCheck.m_belongs)
m_pPolygonizer->EmitFeature(m_Countries[i], m_FB);
}
m_pPolygonizer->m_ThreadPoolSemaphore.release();
}
private:
Polygonizer * m_pPolygonizer;
buffer_vector<kml::CountryPolygons const *, 32> m_Countries;
FeatureBuilder1 m_FB;
};
#endif
};
}