diff --git a/indexer/indexer_tool/feature_generator.cpp b/indexer/indexer_tool/feature_generator.cpp index 1790f532d7..019756914f 100644 --- a/indexer/indexer_tool/feature_generator.cpp +++ b/indexer/indexer_tool/feature_generator.cpp @@ -308,6 +308,7 @@ bool GenerateImpl(GenerateInfo & info) FeaturePolygonizerType bucketer(info); TParser parser(bucketer, holder); ParseXMLFromStdIn(parser); + bucketer.Finish(); info.bucketNames = bucketer.Names(); } else diff --git a/indexer/indexer_tool/polygonizer.hpp b/indexer/indexer_tool/polygonizer.hpp index efd1be172f..c17aae6a19 100644 --- a/indexer/indexer_tool/polygonizer.hpp +++ b/indexer/indexer_tool/polygonizer.hpp @@ -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 +#ifndef PARALLEL_POLYGONIZER +#define PARALLEL_POLYGONIZER 1 +#endif -#include "kml_parser.hpp" -#include "world_map_generator.hpp" +#if PARALLEL_POLYGONIZER +#include +#include +#include +#include +#endif namespace feature { @@ -29,6 +33,9 @@ namespace feature template 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 m_Buckets; vector m_Names; - kml::CountriesContainerT m_countries; - WorldMapGenerator 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 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 m_Countries; + FeatureBuilder1 m_FB; + }; +#endif }; }