mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
Thread pool kinda works.
This commit is contained in:
parent
3d25c2c6dc
commit
a58094aefe
@ -309,7 +309,7 @@ void CMapGenerator::fillZones()
|
||||
}
|
||||
|
||||
//TODO: multiply by the number of modificators
|
||||
Load::Progress::setupStepsTill(numZones, 240);
|
||||
|
||||
std::vector<std::shared_ptr<Zone>> treasureZones;
|
||||
|
||||
ThreadPool pool;
|
||||
@ -318,17 +318,38 @@ void CMapGenerator::fillZones()
|
||||
//At most one Modificator can run for every zone
|
||||
pool.init(std::min<int>(std::thread::hardware_concurrency(), numZones));
|
||||
|
||||
while (hasJobs())
|
||||
TModificators allJobs;
|
||||
for (auto & it : map->getZones())
|
||||
{
|
||||
auto job = getNextJob();
|
||||
if (job)
|
||||
allJobs.splice(allJobs.end(), it.second->getModificators());
|
||||
}
|
||||
|
||||
Load::Progress::setupStepsTill(allJobs.size(), 240);
|
||||
|
||||
while (!allJobs.empty())
|
||||
{
|
||||
for (auto it = allJobs.begin(); it != allJobs.end();)
|
||||
{
|
||||
futures.push_back(pool.async([this, job]() -> void
|
||||
{
|
||||
job.value()();
|
||||
Progress::Progress::step(); //Update progress bar
|
||||
}
|
||||
));
|
||||
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
|
||||
}
|
||||
));
|
||||
it = allJobs.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -441,28 +462,4 @@ Zone * CMapGenerator::getZoneWater() const
|
||||
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
|
||||
|
@ -31,7 +31,7 @@ class CZonePlacer;
|
||||
using JsonVector = std::vector<JsonNode>;
|
||||
|
||||
/// The map generator creates a map randomly.
|
||||
class DLL_LINKAGE CMapGenerator: public Load::Progress, public IJobProvider
|
||||
class DLL_LINKAGE CMapGenerator: public Load::Progress
|
||||
{
|
||||
public:
|
||||
struct Config
|
||||
@ -98,10 +98,6 @@ private:
|
||||
void addHeaderInfo();
|
||||
void genZones();
|
||||
void fillZones();
|
||||
|
||||
TRMGJob getNextJob() override;
|
||||
bool hasJobs() override;
|
||||
|
||||
};
|
||||
|
||||
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)
|
||||
: townType(ETownType::NEUTRAL)
|
||||
: finished(false)
|
||||
, townType(ETownType::NEUTRAL)
|
||||
, terrainType(ETerrainId::GRASS)
|
||||
, map(map)
|
||||
, generator(generator)
|
||||
@ -152,12 +153,12 @@ rmg::Path Zone::searchPath(const rmg::Area & src, bool onlyStraight, const std::
|
||||
return 2;
|
||||
return 3;
|
||||
};
|
||||
|
||||
|
||||
auto area = (dAreaPossible + dAreaFree).getSubarea(areafilter);
|
||||
rmg::Path freePath(area);
|
||||
rmg::Path resultPath(area);
|
||||
freePath.connect(dAreaFree);
|
||||
|
||||
|
||||
//connect to all pieces
|
||||
auto goals = connectedAreas(src, onlyStraight);
|
||||
for(auto & goal : goals)
|
||||
@ -165,42 +166,23 @@ rmg::Path Zone::searchPath(const rmg::Area & src, bool onlyStraight, const std::
|
||||
auto path = freePath.search(goal, onlyStraight, movementCost);
|
||||
if(path.getPathArea().empty())
|
||||
return rmg::Path::invalid();
|
||||
|
||||
|
||||
freePath.connect(path.getPathArea());
|
||||
resultPath.connect(path.getPathArea());
|
||||
}
|
||||
|
||||
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
rmg::Path Zone::searchPath(const int3 & src, bool onlyStraight, const std::function<bool(const int3 &)> & areafilter) const
|
||||
///connect current tile to any other free tile within zone
|
||||
{
|
||||
return searchPath(rmg::Area({src}), onlyStraight, areafilter);
|
||||
return searchPath(rmg::Area({ src }), onlyStraight, areafilter);
|
||||
}
|
||||
|
||||
TRMGJob Zone::getNextJob()
|
||||
TModificators Zone::getModificators()
|
||||
{
|
||||
for (auto& modificator : modificators)
|
||||
{
|
||||
if (modificator->hasJobs())
|
||||
{
|
||||
return modificator->getNextJob();
|
||||
}
|
||||
}
|
||||
return TRMGJob();
|
||||
}
|
||||
|
||||
bool Zone::hasJobs()
|
||||
{
|
||||
for (auto& modificator : modificators)
|
||||
{
|
||||
if (modificator->hasJobs())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return modificators;
|
||||
}
|
||||
|
||||
void Zone::connectPath(const rmg::Path & path)
|
||||
@ -303,21 +285,4 @@ void Zone::initModificators()
|
||||
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
|
||||
|
@ -31,7 +31,9 @@ class Modificator;
|
||||
|
||||
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:
|
||||
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 int3 & src, bool onlyStraight, const std::function<bool(const int3 &)> & areafilter = AREA_NO_FILTER) const;
|
||||
|
||||
TRMGJob getNextJob() override;
|
||||
bool hasJobs() override;
|
||||
//std::vector<std:> & getAllJobs() const;
|
||||
TModificators getModificators();
|
||||
|
||||
template<class T>
|
||||
T* getModificator()
|
||||
@ -85,12 +87,12 @@ public:
|
||||
}
|
||||
|
||||
void initModificators();
|
||||
void processModificators();
|
||||
|
||||
protected:
|
||||
CMapGenerator & generator;
|
||||
RmgMap & map;
|
||||
std::list<std::unique_ptr<Modificator>> modificators;
|
||||
TModificators modificators;
|
||||
bool finished;
|
||||
|
||||
//placement info
|
||||
int3 pos;
|
||||
|
Loading…
Reference in New Issue
Block a user