mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +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 | ||||
| 	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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user