mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-25 22:42:04 +02:00
Thread pool kinda works.
This commit is contained in:
@@ -309,7 +309,7 @@ void CMapGenerator::fillZones()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO: multiply by the number of modificators
|
//TODO: multiply by the number of modificators
|
||||||
Load::Progress::setupStepsTill(numZones, 240);
|
|
||||||
std::vector<std::shared_ptr<Zone>> treasureZones;
|
std::vector<std::shared_ptr<Zone>> treasureZones;
|
||||||
|
|
||||||
ThreadPool pool;
|
ThreadPool pool;
|
||||||
@@ -318,17 +318,38 @@ void CMapGenerator::fillZones()
|
|||||||
//At most one Modificator can run for every zone
|
//At most one Modificator can run for every zone
|
||||||
pool.init(std::min<int>(std::thread::hardware_concurrency(), numZones));
|
pool.init(std::min<int>(std::thread::hardware_concurrency(), numZones));
|
||||||
|
|
||||||
while (hasJobs())
|
TModificators allJobs;
|
||||||
|
for (auto & it : map->getZones())
|
||||||
{
|
{
|
||||||
auto job = getNextJob();
|
allJobs.splice(allJobs.end(), it.second->getModificators());
|
||||||
if (job)
|
}
|
||||||
|
|
||||||
|
Load::Progress::setupStepsTill(allJobs.size(), 240);
|
||||||
|
|
||||||
|
while (!allJobs.empty())
|
||||||
{
|
{
|
||||||
futures.push_back(pool.async([this, job]() -> void
|
for (auto it = allJobs.begin(); it != allJobs.end();)
|
||||||
{
|
{
|
||||||
job.value()();
|
if ((*it)->isFinished())
|
||||||
|
{
|
||||||
|
it = allJobs.erase(it);
|
||||||
|
Progress::Progress::step();
|
||||||
|
}
|
||||||
|
else if ((*it)->isReady())
|
||||||
|
{
|
||||||
|
auto jobCopy = *it;
|
||||||
|
futures.emplace_back(pool.async([this, jobCopy]() -> void
|
||||||
|
{
|
||||||
|
jobCopy->run();
|
||||||
Progress::Progress::step(); //Update progress bar
|
Progress::Progress::step(); //Update progress bar
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
it = allJobs.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,28 +462,4 @@ Zone * CMapGenerator::getZoneWater() const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMapGenerator::hasJobs()
|
|
||||||
{
|
|
||||||
for (auto zone : map->getZones())
|
|
||||||
{
|
|
||||||
if (zone.second->hasJobs())
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRMGJob CMapGenerator::getNextJob()
|
|
||||||
{
|
|
||||||
for (auto zone : map->getZones())
|
|
||||||
{
|
|
||||||
if (zone.second->hasJobs())
|
|
||||||
{
|
|
||||||
return zone.second->getNextJob();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRMGJob();
|
|
||||||
}
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class CZonePlacer;
|
|||||||
using JsonVector = std::vector<JsonNode>;
|
using JsonVector = std::vector<JsonNode>;
|
||||||
|
|
||||||
/// The map generator creates a map randomly.
|
/// The map generator creates a map randomly.
|
||||||
class DLL_LINKAGE CMapGenerator: public Load::Progress, public IJobProvider
|
class DLL_LINKAGE CMapGenerator: public Load::Progress
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct Config
|
struct Config
|
||||||
@@ -98,10 +98,6 @@ private:
|
|||||||
void addHeaderInfo();
|
void addHeaderInfo();
|
||||||
void genZones();
|
void genZones();
|
||||||
void fillZones();
|
void fillZones();
|
||||||
|
|
||||||
TRMGJob getNextJob() override;
|
|
||||||
bool hasJobs() override;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|||||||
159
lib/rmg/Modificator.cpp
Normal file
159
lib/rmg/Modificator.cpp
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* Modificator.cpp, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Modificator.h"
|
||||||
|
#include "Functions.h"
|
||||||
|
#include "CMapGenerator.h"
|
||||||
|
#include "RmgMap.h"
|
||||||
|
#include "../CStopWatch.h"
|
||||||
|
#include "../mapping/CMap.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
Modificator::Modificator(Zone & zone, RmgMap & map, CMapGenerator & generator) : zone(zone), map(map), generator(generator)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Modificator::setName(const std::string & n)
|
||||||
|
{
|
||||||
|
name = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string & Modificator::getName() const
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Modificator::isReady()
|
||||||
|
{
|
||||||
|
Lock lock(mx, boost::try_to_lock_t{});
|
||||||
|
if (!lock.owns_lock())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Check prerequisites
|
||||||
|
for (auto it = preceeders.begin(); it != preceeders.end();)
|
||||||
|
{
|
||||||
|
if ((*it)->isFinished()) //OK
|
||||||
|
{
|
||||||
|
it = preceeders.erase(it);
|
||||||
|
}
|
||||||
|
else if (!(*it)->isReady())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !finished;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Modificator::isFinished()
|
||||||
|
{
|
||||||
|
Lock lock(mx, boost::try_to_lock_t{});
|
||||||
|
if (!lock.owns_lock())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return finished;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Modificator::run()
|
||||||
|
{
|
||||||
|
Lock lock(mx);
|
||||||
|
|
||||||
|
if(!finished)
|
||||||
|
{
|
||||||
|
logGlobal->info("Modificator zone %d - %s - started", zone.getId(), getName());
|
||||||
|
CStopWatch processTime;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
process();
|
||||||
|
}
|
||||||
|
catch(rmgException &e)
|
||||||
|
{
|
||||||
|
logGlobal->error("Modificator %s, exception: %s", getName(), e.what());
|
||||||
|
}
|
||||||
|
#ifdef RMG_DUMP
|
||||||
|
dump();
|
||||||
|
#endif
|
||||||
|
finished = true;
|
||||||
|
logGlobal->info("Modificator zone %d - %s - done (%d ms)", zone.getId(), getName(), processTime.getDiff());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Modificator::dependency(Modificator * modificator)
|
||||||
|
{
|
||||||
|
if(modificator && modificator != this)
|
||||||
|
{
|
||||||
|
if(std::find(preceeders.begin(), preceeders.end(), modificator) == preceeders.end())
|
||||||
|
preceeders.push_back(modificator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Modificator::postfunction(Modificator * modificator)
|
||||||
|
{
|
||||||
|
if(modificator && modificator != this)
|
||||||
|
{
|
||||||
|
if(std::find(modificator->preceeders.begin(), modificator->preceeders.end(), this) == modificator->preceeders.end())
|
||||||
|
modificator->preceeders.push_back(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Modificator::dump()
|
||||||
|
{
|
||||||
|
std::ofstream out(boost::to_string(boost::format("seed_%d_modzone_%d_%s.txt") % generator.getRandomSeed() % zone.getId() % getName()));
|
||||||
|
auto & mapInstance = map.map();
|
||||||
|
int levels = mapInstance.levels();
|
||||||
|
int width = mapInstance.width;
|
||||||
|
int height = mapInstance.height;
|
||||||
|
for(int z = 0; z < levels; z++)
|
||||||
|
{
|
||||||
|
for(int j=0; j<height; j++)
|
||||||
|
{
|
||||||
|
for(int i=0; i<width; i++)
|
||||||
|
{
|
||||||
|
out << dump(int3(i, j, z));
|
||||||
|
}
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
char Modificator::dump(const int3 & t)
|
||||||
|
{
|
||||||
|
if(zone.freePaths().contains(t))
|
||||||
|
return '.'; //free path
|
||||||
|
if(zone.areaPossible().contains(t))
|
||||||
|
return ' '; //possible
|
||||||
|
if(zone.areaUsed().contains(t))
|
||||||
|
return 'U'; //used
|
||||||
|
if(zone.area().contains(t))
|
||||||
|
{
|
||||||
|
if(map.shouldBeBlocked(t))
|
||||||
|
return '#'; //obstacle
|
||||||
|
else
|
||||||
|
return '^'; //visitable points?
|
||||||
|
}
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
||||||
80
lib/rmg/Modificator.h
Normal file
80
lib/rmg/Modificator.h
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Modificator.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../GameConstants.h"
|
||||||
|
#include "../int3.h"
|
||||||
|
#include "threadpool/JobProvider.h"
|
||||||
|
#include "Zone.h"
|
||||||
|
|
||||||
|
class RmgMap;
|
||||||
|
class CMapGenerator;
|
||||||
|
class Zone;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define MODIFICATOR(x) x(Zone & z, RmgMap & m, CMapGenerator & g): Modificator(z, m, g) {setName(#x);}
|
||||||
|
#define DEPENDENCY(x) dependency(zone.getModificator<x>());
|
||||||
|
#define POSTFUNCTION(x) postfunction(zone.getModificator<x>());
|
||||||
|
#define DEPENDENCY_ALL(x) for(auto & z : map.getZones()) \
|
||||||
|
{ \
|
||||||
|
dependency(z.second->getModificator<x>()); \
|
||||||
|
}
|
||||||
|
#define POSTFUNCTION_ALL(x) for(auto & z : map.getZones()) \
|
||||||
|
{ \
|
||||||
|
postfunction(z.second->getModificator<x>()); \
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class Modificator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Modificator() = delete;
|
||||||
|
Modificator(Zone & zone, RmgMap & map, CMapGenerator & generator);
|
||||||
|
|
||||||
|
virtual void init() {/*override to add dependencies*/}
|
||||||
|
virtual char dump(const int3 &);
|
||||||
|
virtual ~Modificator() = default;
|
||||||
|
|
||||||
|
void setName(const std::string & n);
|
||||||
|
const std::string & getName() const;
|
||||||
|
|
||||||
|
bool isReady();
|
||||||
|
bool isFinished();
|
||||||
|
|
||||||
|
void run();
|
||||||
|
void dependency(Modificator * modificator);
|
||||||
|
void postfunction(Modificator * modificator);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
RmgMap & map;
|
||||||
|
CMapGenerator & generator;
|
||||||
|
Zone & zone;
|
||||||
|
|
||||||
|
bool finished = false;
|
||||||
|
|
||||||
|
//bool wasStarted() const;
|
||||||
|
private:
|
||||||
|
virtual void process() = 0;
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
//bool started = false;
|
||||||
|
|
||||||
|
std::list<Modificator*> preceeders; //must be ordered container
|
||||||
|
|
||||||
|
mutable boost::shared_mutex mx;
|
||||||
|
using Lock = boost::unique_lock<boost::shared_mutex>;
|
||||||
|
|
||||||
|
void dump();
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
||||||
@@ -24,7 +24,8 @@ std::function<bool(const int3 &)> AREA_NO_FILTER = [](const int3 & t)
|
|||||||
};
|
};
|
||||||
|
|
||||||
Zone::Zone(RmgMap & map, CMapGenerator & generator)
|
Zone::Zone(RmgMap & map, CMapGenerator & generator)
|
||||||
: townType(ETownType::NEUTRAL)
|
: finished(false)
|
||||||
|
, townType(ETownType::NEUTRAL)
|
||||||
, terrainType(ETerrainId::GRASS)
|
, terrainType(ETerrainId::GRASS)
|
||||||
, map(map)
|
, map(map)
|
||||||
, generator(generator)
|
, generator(generator)
|
||||||
@@ -179,28 +180,9 @@ rmg::Path Zone::searchPath(const int3 & src, bool onlyStraight, const std::funct
|
|||||||
return searchPath(rmg::Area({ src }), onlyStraight, areafilter);
|
return searchPath(rmg::Area({ src }), onlyStraight, areafilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRMGJob Zone::getNextJob()
|
TModificators Zone::getModificators()
|
||||||
{
|
{
|
||||||
for (auto& modificator : modificators)
|
return modificators;
|
||||||
{
|
|
||||||
if (modificator->hasJobs())
|
|
||||||
{
|
|
||||||
return modificator->getNextJob();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRMGJob();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Zone::hasJobs()
|
|
||||||
{
|
|
||||||
for (auto& modificator : modificators)
|
|
||||||
{
|
|
||||||
if (modificator->hasJobs())
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Zone::connectPath(const rmg::Path & path)
|
void Zone::connectPath(const rmg::Path & path)
|
||||||
@@ -303,21 +285,4 @@ void Zone::initModificators()
|
|||||||
logGlobal->info("Zone %d modificators initialized", getId());
|
logGlobal->info("Zone %d modificators initialized", getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Zone::processModificators()
|
|
||||||
{
|
|
||||||
for(auto & modificator : modificators)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
modificator->run();
|
|
||||||
}
|
|
||||||
catch (const rmgException & e)
|
|
||||||
{
|
|
||||||
logGlobal->info("Zone %d, modificator %s - FAILED: %s", getId(), e.what());
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logGlobal->info("Zone %d filled successfully", getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ class Modificator;
|
|||||||
|
|
||||||
extern std::function<bool(const int3 &)> AREA_NO_FILTER;
|
extern std::function<bool(const int3 &)> AREA_NO_FILTER;
|
||||||
|
|
||||||
class Zone : public rmg::ZoneOptions, public IJobProvider
|
typedef std::list<std::shared_ptr<Modificator>> TModificators;
|
||||||
|
|
||||||
|
class Zone : public rmg::ZoneOptions
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Zone(RmgMap & map, CMapGenerator & generator);
|
Zone(RmgMap & map, CMapGenerator & generator);
|
||||||
@@ -64,8 +66,8 @@ public:
|
|||||||
rmg::Path searchPath(const rmg::Area & src, bool onlyStraight, const std::function<bool(const int3 &)> & areafilter = AREA_NO_FILTER) const;
|
rmg::Path searchPath(const rmg::Area & src, bool onlyStraight, const std::function<bool(const int3 &)> & areafilter = AREA_NO_FILTER) const;
|
||||||
rmg::Path searchPath(const int3 & src, bool onlyStraight, const std::function<bool(const int3 &)> & areafilter = AREA_NO_FILTER) const;
|
rmg::Path searchPath(const int3 & src, bool onlyStraight, const std::function<bool(const int3 &)> & areafilter = AREA_NO_FILTER) const;
|
||||||
|
|
||||||
TRMGJob getNextJob() override;
|
//std::vector<std:> & getAllJobs() const;
|
||||||
bool hasJobs() override;
|
TModificators getModificators();
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T* getModificator()
|
T* getModificator()
|
||||||
@@ -85,12 +87,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void initModificators();
|
void initModificators();
|
||||||
void processModificators();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CMapGenerator & generator;
|
CMapGenerator & generator;
|
||||||
RmgMap & map;
|
RmgMap & map;
|
||||||
std::list<std::unique_ptr<Modificator>> modificators;
|
TModificators modificators;
|
||||||
|
bool finished;
|
||||||
|
|
||||||
//placement info
|
//placement info
|
||||||
int3 pos;
|
int3 pos;
|
||||||
|
|||||||
Reference in New Issue
Block a user