diff --git a/source/glest_game/type_instances/faction.cpp b/source/glest_game/type_instances/faction.cpp index 04f756b2..0c0639fc 100644 --- a/source/glest_game/type_instances/faction.cpp +++ b/source/glest_game/type_instances/faction.cpp @@ -36,14 +36,21 @@ CommandGroupSorter::CommandGroupSorter(Unit *unit) { bool CommandGroupSorter::operator< (const CommandGroupSorter &j) const { - Command *command= this->unit->getCurrCommand(); + if(j.unit == NULL || j.unit->isAlive() == false) { + return true; + } + else if((this->unit == NULL || this->unit->isAlive() == false)) { + return false; + } + + Command *command= this->unit->getCurrrentCommandThreadSafe(); if( command != NULL && (command->getCommandType()->getClass() == ccMove || command->getCommandType()->getClass() == ccAttack) && command->getUnitCommandGroupId() > 0) { int curCommandGroupId = command->getUnitCommandGroupId(); - Command *commandPeer = j.unit->getCurrCommand(); + Command *commandPeer = j.unit->getCurrrentCommandThreadSafe(); if(commandPeer == NULL) { return true; } diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index 2fe7298a..5800656a 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -338,10 +338,14 @@ Unit::~Unit() { } //remove commands + static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__); + MutexSafeWrapper safeMutex(&mutexCommands,mutexOwnerId); + while(commands.empty() == false) { delete commands.back(); commands.pop_back(); } + safeMutex.ReleaseLock(); // If the unit is not visible we better make sure we cleanup associated particles if(this->getVisible() == false) { @@ -865,6 +869,17 @@ bool Unit::anyCommand(bool validateCommandtype) const { return result; } +//return current command, assert that there is always one command +Command *Unit::getCurrrentCommandThreadSafe() { + static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__); + MutexSafeWrapper safeMutex(&mutexCommands,mutexOwnerId); + + if(commands.empty() == false) { + return commands.front(); + } + return NULL; +} + //return current command, assert that there is always one command Command *Unit::getCurrCommand() const { if(commands.empty() == false) { @@ -933,6 +948,9 @@ CommandResult Unit::giveCommand(Command *command, bool tryQueue) { } else{ //Delete all lower-prioirty commands + static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__); + MutexSafeWrapper safeMutex(&mutexCommands,mutexOwnerId); + for(list::iterator i= commands.begin(); i != commands.end();){ if((*i)->getPriority() < command_priority){ if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) @@ -945,6 +963,7 @@ CommandResult Unit::giveCommand(Command *command, bool tryQueue) { ++i; } } + safeMutex.ReleaseLock(); } if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); @@ -984,7 +1003,12 @@ CommandResult Unit::giveCommand(Command *command, bool tryQueue) { //push back command if(result == crSuccess) { + static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__); + MutexSafeWrapper safeMutex(&mutexCommands,mutexOwnerId); + commands.push_back(command); + + safeMutex.ReleaseLock(); } else { delete command; @@ -1007,6 +1031,9 @@ CommandResult Unit::finishCommand() { } //pop front + static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__); + MutexSafeWrapper safeMutex(&mutexCommands,mutexOwnerId); + delete commands.front(); commands.erase(commands.begin()); this->unitPath->clear(); @@ -1020,6 +1047,8 @@ CommandResult Unit::finishCommand() { } } + safeMutex.ReleaseLock(); + return crSuccess; } @@ -1039,12 +1068,16 @@ CommandResult Unit::cancelCommand() { undoCommand(commands.back()); //delete ans pop command + static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__); + MutexSafeWrapper safeMutex(&mutexCommands,mutexOwnerId); + delete commands.back(); commands.pop_back(); //clear routes this->unitPath->clear(); + safeMutex.ReleaseLock(); return crSuccess; } @@ -2044,6 +2077,9 @@ void Unit::updateTarget(){ } void Unit::clearCommands() { + static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__); + MutexSafeWrapper safeMutex(&mutexCommands,mutexOwnerId); + this->setCurrentUnitTitle(""); this->unitPath->clear(); while(commands.empty() == false) { diff --git a/source/glest_game/type_instances/unit.h b/source/glest_game/type_instances/unit.h index 7287082b..94221d91 100644 --- a/source/glest_game/type_instances/unit.h +++ b/source/glest_game/type_instances/unit.h @@ -375,6 +375,8 @@ private: std::vector currentAttackBoostEffects; + Mutex mutexCommands; + public: Unit(int id, UnitPathInterface *path, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, CardinalDir placeFacing); ~Unit(); @@ -386,6 +388,7 @@ public: bool unitHasAttackBoost(const AttackBoost *boost, const Unit *source) const; //queries + Command *getCurrrentCommandThreadSafe(); void setIgnoreCheckCommand(bool value) { ignoreCheckCommand=value;} bool getIgnoreCheckCommand() const {return ignoreCheckCommand;} int getId() const {return id;}