From ece2927350adc25c3bd8624c1bcefa402cef0deb Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Sun, 25 Sep 2011 04:07:59 +0000 Subject: [PATCH] - attempt to fix command grouping --- source/glest_game/type_instances/faction.cpp | 117 ++++++++++++++++++- source/glest_game/type_instances/faction.h | 15 ++- source/glest_game/type_instances/unit.cpp | 20 ++++ source/glest_game/type_instances/unit.h | 8 ++ source/glest_game/world/world.cpp | 62 ++++++---- source/glest_game/world/world.h | 11 +- 6 files changed, 196 insertions(+), 37 deletions(-) diff --git a/source/glest_game/type_instances/faction.cpp b/source/glest_game/type_instances/faction.cpp index 93991c88..f6742113 100644 --- a/source/glest_game/type_instances/faction.cpp +++ b/source/glest_game/type_instances/faction.cpp @@ -30,7 +30,36 @@ using Shared::Util::RandomGen; namespace Glest { namespace Game { +bool CommandGroupUnitSorterId::operator()(const int l, const int r) { + const Unit *lUnit = faction->findUnit(l); + const Unit *rUnit = faction->findUnit(r); + + if(!lUnit) { + printf("Error lUnit == NULL for id = %d factionIndex = %d\n",l,faction->getIndex()); + + for(unsigned int i = 0; i < faction->getUnitCount(); ++i) { + printf("%d / %d id = %d [%s]\n",i,faction->getUnitCount(),faction->getUnit(i)->getId(),faction->getUnit(i)->getType()->getName().c_str()); + } + } + if(!rUnit) { + printf("Error rUnit == NULL for id = %d factionIndex = %d\n",r,faction->getIndex()); + + for(unsigned int i = 0; i < faction->getUnitCount(); ++i) { + printf("%d / %d id = %d [%s]\n",i,faction->getUnitCount(),faction->getUnit(i)->getId(),faction->getUnit(i)->getType()->getName().c_str()); + } + } + + CommandGroupUnitSorter sorter; + return sorter.compare(lUnit, rUnit); +} + bool CommandGroupUnitSorter::operator()(const Unit *l, const Unit *r) { + return compare(l, r); +} + +bool CommandGroupUnitSorter::compare(const Unit *l, const Unit *r) { + //printf("l [%p] r [%p] <>",l,r); + if(!l) { printf("Error l == NULL\n"); } @@ -49,7 +78,7 @@ bool CommandGroupUnitSorter::operator()(const Unit *l, const Unit *r) { bool result = false; - // If comparer if null or dead + // If comparer is null or dead if(r == NULL || r->isAlive() == false) { // if source is null or dead also if((l == NULL || l->isAlive() == false)) { @@ -69,7 +98,7 @@ bool CommandGroupUnitSorter::operator()(const Unit *l, const Unit *r) { //Command *command= this->unit->getCurrCommand(); // Are we moving or attacking - if( command != NULL && + if( command != NULL && command->getCommandType() != NULL && (command->getCommandType()->getClass() == ccMove || command->getCommandType()->getClass() == ccAttack) && command->getUnitCommandGroupId() > 0) { @@ -79,7 +108,7 @@ bool CommandGroupUnitSorter::operator()(const Unit *l, const Unit *r) { //Command *commandPeer = j.unit->getCurrCommand(); // is comparer a valid command - if(commandPeer == NULL) { + if(commandPeer == NULL || commandPeer->getCommandType() == NULL) { result = true; } // is comparer command the same type? @@ -111,7 +140,7 @@ bool CommandGroupUnitSorter::operator()(const Unit *l, const Unit *r) { // } else { //Command *commandPeer = j.unit->getCurrrentCommandThreadSafe(); - if( commandPeer != NULL && + if( commandPeer != NULL && commandPeer->getCommandType() != NULL && (commandPeer->getCommandType()->getClass() != ccMove && commandPeer->getCommandType()->getClass() != ccAttack)) { result = l->getId() < r->getId(); @@ -127,7 +156,53 @@ bool CommandGroupUnitSorter::operator()(const Unit *l, const Unit *r) { } void Faction::sortUnitsByCommandGroups() { - std::sort(units.begin(),units.end(),CommandGroupUnitSorter()); + MutexSafeWrapper safeMutex(unitsMutex,string(__FILE__) + "_" + intToStr(__LINE__)); + //printf("====== sortUnitsByCommandGroups for faction # %d [%s] unitCount = %d\n",this->getIndex(),this->getType()->getName().c_str(),units.size()); + //for(unsigned int i = 0; i < units.size(); ++i) { + // printf("%d / %d [%p] <>",i,units.size(),&units[i]); +// // printf("i = %d [%p]\n",i,&units[i]); +// if(Unit::isUnitDeleted(units[i]) == true) { +// printf("i = %d [%p]\n",i,&units[i]); +// throw runtime_error("unit already deleted!"); +// } + //} + //printf("\nSorting\n"); + + //std::sort(units.begin(),units.end(),CommandGroupUnitSorter()); + + //printf("====== Done sorting for faction # %d [%s] unitCount = %d\n",this->getIndex(),this->getType()->getName().c_str(),units.size()); + + std::vector unitIds; + for(unsigned int i = 0; i < units.size(); ++i) { + int unitId = units[i]->getId(); + if(this->findUnit(unitId) == NULL) { + printf("#1 Error unitId not found for id = %d [%s] factionIndex = %d\n",unitId,units[i]->getType()->getName().c_str(),this->getIndex()); + + for(unsigned int j = 0; j < units.size(); ++j) { + printf("%d / %d id = %d [%s]\n",j,units.size(),units[j]->getId(),units[j]->getType()->getName().c_str()); + } + } + unitIds.push_back(unitId); + } + CommandGroupUnitSorterId sorter; + sorter.faction = this; + std::stable_sort(unitIds.begin(),unitIds.end(),sorter); + + units.clear(); + for(unsigned int i = 0; i < unitIds.size(); ++i) { + + int unitId = unitIds[i]; + if(this->findUnit(unitId) == NULL) { + printf("#2 Error unitId not found for id = %d factionIndex = %d\n",unitId,this->getIndex()); + + for(unsigned int j = 0; j < units.size(); ++j) { + printf("%d / %d id = %d [%s]\n",j,units.size(),units[j]->getId(),units[j]->getType()->getName().c_str()); + } + } + + units.push_back(this->findUnit(unitId)); + } + } // ===================================================== @@ -231,6 +306,13 @@ void FactionThread::execute() { World *world = faction->getWorld(); + Config &config= Config::getInstance(); + bool sortedUnitsAllowed = config.getBool("AllowGroupedUnitCommands","true"); + if(sortedUnitsAllowed) { + faction->sortUnitsByCommandGroups(); + } + + MutexSafeWrapper safeMutex(faction->getUnitMutex(),string(__FILE__) + "_" + intToStr(__LINE__)); int unitCount = faction->getUnitCount(); for(int j = 0; j < unitCount; ++j) { Unit *unit = faction->getUnit(j); @@ -244,6 +326,7 @@ void FactionThread::execute() { world->getUnitUpdater()->updateUnitCommand(unit,frameIndex.first); } } + safeMutex.ReleaseLock(); setTaskCompleted(frameIndex.first); } @@ -274,6 +357,7 @@ void FactionThread::execute() { // ===================================================== Faction::Faction() { + unitsMutex = new Mutex(); texture = NULL; //lastResourceTargettListPurge = 0; cachingDisabled=false; @@ -311,6 +395,21 @@ Faction::~Faction() { //delete texture; texture = NULL; if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + + delete unitsMutex; + unitsMutex = NULL; + + if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); +} + +Unit * Faction::getUnit(int i) const { + Unit *result = units[i]; + return result; +} + +int Faction::getUnitCount() const { + int result = units.size(); + return result; } void Faction::signalWorkerThread(int frameIndex) { @@ -384,7 +483,10 @@ void Faction::end() { workerThread = NULL; } + MutexSafeWrapper safeMutex(unitsMutex,string(__FILE__) + "_" + intToStr(__LINE__)); deleteValues(units.begin(), units.end()); + safeMutex.ReleaseLock(); + if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } @@ -798,12 +900,15 @@ Unit *Faction::findUnit(int id) const { return itFound->second; } -void Faction::addUnit(Unit *unit){ +void Faction::addUnit(Unit *unit) { + MutexSafeWrapper safeMutex(unitsMutex,string(__FILE__) + "_" + intToStr(__LINE__)); units.push_back(unit); unitMap[unit->getId()] = unit; } void Faction::removeUnit(Unit *unit){ + MutexSafeWrapper safeMutex(unitsMutex,string(__FILE__) + "_" + intToStr(__LINE__)); + assert(units.size()==unitMap.size()); int unitId = unit->getId(); diff --git a/source/glest_game/type_instances/faction.h b/source/glest_game/type_instances/faction.h index e35c7c1b..f35ac5bd 100644 --- a/source/glest_game/type_instances/faction.h +++ b/source/glest_game/type_instances/faction.h @@ -51,6 +51,12 @@ class Faction; struct CommandGroupUnitSorter { bool operator()(const Unit *l, const Unit *r); + bool compare(const Unit *l, const Unit *r); +}; + +struct CommandGroupUnitSorterId { + Faction *faction; + bool operator()(const int l, const int r); }; class FactionThread : public BaseThread { @@ -96,6 +102,8 @@ private: Resources resources; Store store; Allies allies; + + Mutex *unitsMutex; Units units; UnitMap unitMap; World *world; @@ -158,8 +166,11 @@ public: bool getCpuUltraControl() const {return control==ctCpuUltra;} bool getCpuMegaControl() const {return control==ctCpuMega;} ControlType getControlType() const {return control;} - Unit *getUnit(int i) const {return units[i];} - int getUnitCount() const {return units.size();} + + Unit *getUnit(int i) const; + int getUnitCount() const; + Mutex * getUnitMutex() {return unitsMutex;} + const UpgradeManager *getUpgradeManager() const {return &upgradeManager;} const Texture2D *getTexture() const {return texture;} int getStartLocationIndex() const {return startLocationIndex;} diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index f3a2c343..bc9ec152 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -35,6 +35,9 @@ using namespace Shared::Util; namespace Glest{ namespace Game{ +//Mutex Unit::mutexDeletedUnits; +//map Unit::deletedUnits; + const int UnitPathBasic::maxBlockCount= GameConstants::updateFps / 2; UnitPathBasic::UnitPathBasic() { @@ -344,6 +347,11 @@ Unit::Unit(int id, UnitPathInterface *unitpath, const Vec2i &pos, const UnitType addItemToVault(&this->hp,this->hp); addItemToVault(&this->ep,this->ep); +// if(isUnitDeleted(this) == true) { +// MutexSafeWrapper safeMutex(&mutexDeletedUnits,string(__FILE__) + "_" + intToStr(__LINE__)); +// deletedUnits.erase(this); +// } + logSynchData(__FILE__,__LINE__); } @@ -406,8 +414,20 @@ Unit::~Unit() { Renderer &renderer= Renderer::getInstance(); renderer.removeUnitFromQuadCache(this); + + //MutexSafeWrapper safeMutex1(&mutexDeletedUnits,string(__FILE__) + "_" + intToStr(__LINE__)); + //deletedUnits[this]=true; } +//bool Unit::isUnitDeleted(void *unit) { +// bool result = false; +// MutexSafeWrapper safeMutex(&mutexDeletedUnits,string(__FILE__) + "_" + intToStr(__LINE__)); +// if(deletedUnits.find(unit) != deletedUnits.end()) { +// result = true; +// } +// return result; +//} + void Unit::setModelFacing(CardinalDir value) { modelFacing = value; lastRotation = targetRotation = rotation = value * 90.f; diff --git a/source/glest_game/type_instances/unit.h b/source/glest_game/type_instances/unit.h index 183ff67f..1f9bf831 100644 --- a/source/glest_game/type_instances/unit.h +++ b/source/glest_game/type_instances/unit.h @@ -383,10 +383,18 @@ private: Mutex mutexCommands; + //static Mutex mutexDeletedUnits; + //static std::map deletedUnits; + public: + Unit() : id(-1) { + assert(false); + } Unit(int id, UnitPathInterface *path, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, CardinalDir placeFacing); ~Unit(); + //static bool isUnitDeleted(void *unit); + static void setGame(Game *value) { game=value;} //const std::pair > & getCurrentAttackBoostUnits() const { return currentAttackBoostUnits; } diff --git a/source/glest_game/world/world.cpp b/source/glest_game/world/world.cpp index 35efa4e7..6f7b3a6d 100644 --- a/source/glest_game/world/world.cpp +++ b/source/glest_game/world/world.cpp @@ -93,10 +93,13 @@ World::~World() { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); for(int i= 0; iend(); } if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + for(int i= 0; iend(); + } + for(int i= 0; isortUnitsByCommandGroups(); - } - } +// Config &config= Config::getInstance(); +// bool sortedUnitsAllowed = config.getBool("AllowGroupedUnitCommands","true"); +// +// int factionCount = getFactionCount(); +// if(sortedUnitsAllowed == true) { +// for(int i = 0; i < factionCount; ++i) { +// Faction *faction = getFaction(i); +// if(faction == NULL) { +// throw runtime_error("faction == NULL"); +// } +// +// // Sort units by command groups +// faction->sortUnitsByCommandGroups(); +// } +// } // Signal the faction threads to do any pre-processing for(int i = 0; i < factionCount; ++i) { @@ -771,7 +780,7 @@ void World::createUnit(const string &unitName, int factionIndex, const Vec2i &po if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] unitName [%s] factionIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,unitName.c_str(),factionIndex); if(factionIndex < factions.size()) { - Faction* faction= &factions[factionIndex]; + Faction* faction= factions[factionIndex]; if(faction->getIndex() != factionIndex) { throw runtime_error("faction->getIndex() != factionIndex"); @@ -818,7 +827,7 @@ void World::createUnit(const string &unitName, int factionIndex, const Vec2i &po void World::giveResource(const string &resourceName, int factionIndex, int amount) { if(factionIndex < factions.size()) { - Faction* faction= &factions[factionIndex]; + Faction* faction= factions[factionIndex]; const ResourceType* rt= techTree->getResourceType(resourceName); faction->incResourceAmount(rt, amount); } @@ -1041,7 +1050,7 @@ void World::giveUpgradeCommand(int unitId, const string &upgradeName) { int World::getResourceAmount(const string &resourceName, int factionIndex) { if(factionIndex < factions.size()) { - Faction* faction= &factions[factionIndex]; + Faction* faction= factions[factionIndex]; const ResourceType* rt= techTree->getResourceType(resourceName); return faction->getResource(rt)->getAmount(); } @@ -1052,7 +1061,7 @@ int World::getResourceAmount(const string &resourceName, int factionIndex) { Vec2i World::getStartLocation(int factionIndex) { if(factionIndex < factions.size()) { - Faction* faction= &factions[factionIndex]; + Faction* faction= factions[factionIndex]; return map.getStartLocation(faction->getStartLocationIndex()); } else { @@ -1078,7 +1087,7 @@ int World::getUnitFactionIndex(int unitId) { int World::getUnitCount(int factionIndex) { if(factionIndex < factions.size()) { - Faction* faction= &factions[factionIndex]; + Faction* faction= factions[factionIndex]; int count= 0; for(int i= 0; i < faction->getUnitCount(); ++i) { @@ -1096,7 +1105,7 @@ int World::getUnitCount(int factionIndex) { int World::getUnitCountOfType(int factionIndex, const string &typeName) { if(factionIndex < factions.size()) { - Faction* faction= &factions[factionIndex]; + Faction* faction= factions[factionIndex]; int count= 0; for(int i= 0; i< faction->getUnitCount(); ++i) { @@ -1205,7 +1214,11 @@ void World::initFactionTypes(GameSettings *gs) { //create factions this->thisFactionIndex= gs->getThisFactionIndex(); - factions.resize(gs->getFactionCount()); + //factions.resize(gs->getFactionCount()); + for(int i= 0; i < gs->getFactionCount(); ++i){ + Faction *newFaction = new Faction(); + factions.push_back(newFaction); + } if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] factions.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,factions.size()); @@ -1214,7 +1227,7 @@ void World::initFactionTypes(GameSettings *gs) { if(ft == NULL) { throw runtime_error("ft == NULL"); } - factions[i].init(ft, gs->getFactionControl(i), techTree, game, i, gs->getTeam(i), + factions[i]->init(ft, gs->getFactionControl(i), techTree, game, i, gs->getTeam(i), gs->getStartLocationIndex(i), i==thisFactionIndex, gs->getDefaultResources()); stats.setTeam(i, gs->getTeam(i)); @@ -1250,7 +1263,7 @@ void World::initUnits() { //put starting units for(int i = 0; i < getFactionCount(); ++i) { - Faction *f= &factions[i]; + Faction *f= factions[i]; const FactionType *ft= f->getType(); for(int j = 0; j < ft->getStartingUnitCount(); ++j) { @@ -1664,6 +1677,7 @@ const GameSettings * World::getGameSettings() const { // Calculates the unit unit ID for each faction // int World::getNextUnitId(Faction *faction) { + MutexSafeWrapper safeMutex(&mutexFactionNextUnitId,string(__FILE__) + "_" + intToStr(__LINE__)); if(mapFactionNextUnitId.find(faction->getIndex()) == mapFactionNextUnitId.end()) { mapFactionNextUnitId[faction->getIndex()] = faction->getIndex() * 100000; } diff --git a/source/glest_game/world/world.h b/source/glest_game/world/world.h index 74e0a7db..66235f9f 100644 --- a/source/glest_game/world/world.h +++ b/source/glest_game/world/world.h @@ -84,7 +84,7 @@ public: class World{ private: - typedef vector Factions; + typedef vector Factions; std::map > ExploredCellsLookupItemCache; std::map ExploredCellsLookupItemCacheTimer; @@ -124,6 +124,7 @@ private: int thisTeamIndex; int frameCount; //int nextUnitId; + Mutex mutexFactionNextUnitId; std::map mapFactionNextUnitId; //config @@ -154,8 +155,8 @@ public: int getThisTeamIndex() const {return thisTeamIndex;} void setThisTeamIndex(int team) { thisTeamIndex=team;} - const Faction *getThisFaction() const {return &factions[thisFactionIndex];} - Faction *getThisFactionPtr() {return &factions[thisFactionIndex];} + const Faction *getThisFaction() const {return factions[thisFactionIndex];} + Faction *getThisFactionPtr() {return factions[thisFactionIndex];} int getFactionCount() const {return factions.size();} const Map *getMap() const {return ↦} @@ -167,8 +168,8 @@ public: Map *getMap() {return ↦} Cartographer* getCartographer() {return cartographer;} RoutePlanner* getRoutePlanner() {return routePlanner;} - const Faction *getFaction(int i) const {return &factions[i];} - Faction *getFaction(int i) {return &factions[i];} + const Faction *getFaction(int i) const {return factions[i];} + Faction *getFaction(int i) {return factions[i];} const Minimap *getMinimap() const {return &minimap;} Minimap *getMiniMapObject() {return &minimap;} const Stats *getStats() const {return &stats;};