1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

Fix a few crashes

This commit is contained in:
Andrii Danylchenko
2022-04-04 10:16:32 +03:00
committed by Andrii Danylchenko
parent b97e5817ce
commit fa9a420f99
4 changed files with 54 additions and 13 deletions

View File

@@ -1148,7 +1148,7 @@ bool AINodeStorage::hasBetterChain(
{ {
auto sameNode = node.actor == candidateNode->actor; auto sameNode = node.actor == candidateNode->actor;
if(sameNode || node.action == CGPathNode::ENodeAction::UNKNOWN || !node.actor->hero) if(sameNode || node.action == CGPathNode::ENodeAction::UNKNOWN || !node.actor || !node.actor->hero)
{ {
continue; continue;
} }

View File

@@ -2799,6 +2799,11 @@ void CBattleInterface::requestAutofightingAIToTakeAction()
{ {
auto ba = make_unique<BattleAction>(curInt->autofightingAI->activeStack(activeStack)); auto ba = make_unique<BattleAction>(curInt->autofightingAI->activeStack(activeStack));
if(curInt->cb->battleIsFinished())
{
return; // battle finished with spellcast
}
if (curInt->isAutoFightOn) if (curInt->isAutoFightOn)
{ {
if (tacticsMode) if (tacticsMode)

View File

@@ -97,7 +97,9 @@ CBonusProxy::CBonusProxy(const IBonusBearer * Target, CSelector Selector)
: bonusListCachedLast(0), : bonusListCachedLast(0),
target(Target), target(Target),
selector(Selector), selector(Selector),
bonusList() bonusList(),
currentBonusListIndex(0),
swapGuard()
{ {
} }
@@ -106,27 +108,34 @@ CBonusProxy::CBonusProxy(const CBonusProxy & other)
: bonusListCachedLast(other.bonusListCachedLast), : bonusListCachedLast(other.bonusListCachedLast),
target(other.target), target(other.target),
selector(other.selector), selector(other.selector),
bonusList(other.bonusList) currentBonusListIndex(other.currentBonusListIndex),
swapGuard()
{ {
bonusList[currentBonusListIndex] = other.bonusList[currentBonusListIndex];
} }
CBonusProxy::CBonusProxy(CBonusProxy && other) CBonusProxy::CBonusProxy(CBonusProxy && other)
: bonusListCachedLast(0), : bonusListCachedLast(0),
target(other.target), target(other.target),
selector(), selector(),
bonusList() bonusList(),
currentBonusListIndex(0),
swapGuard()
{ {
std::swap(bonusListCachedLast, other.bonusListCachedLast); std::swap(bonusListCachedLast, other.bonusListCachedLast);
std::swap(selector, other.selector); std::swap(selector, other.selector);
std::swap(bonusList, other.bonusList); std::swap(bonusList, other.bonusList);
std::swap(currentBonusListIndex, other.currentBonusListIndex);
} }
CBonusProxy & CBonusProxy::operator=(const CBonusProxy & other) CBonusProxy & CBonusProxy::operator=(const CBonusProxy & other)
{ {
bonusListCachedLast = other.bonusListCachedLast; boost::lock_guard<boost::mutex> lock(swapGuard);
selector = other.selector; selector = other.selector;
bonusList = other.bonusList; swapBonusList(other.bonusList[other.currentBonusListIndex]);
bonusListCachedLast = other.bonusListCachedLast;
return *this; return *this;
} }
@@ -135,18 +144,42 @@ CBonusProxy & CBonusProxy::operator=(CBonusProxy && other)
std::swap(bonusListCachedLast, other.bonusListCachedLast); std::swap(bonusListCachedLast, other.bonusListCachedLast);
std::swap(selector, other.selector); std::swap(selector, other.selector);
std::swap(bonusList, other.bonusList); std::swap(bonusList, other.bonusList);
std::swap(currentBonusListIndex, other.currentBonusListIndex);
return *this; return *this;
} }
void CBonusProxy::swapBonusList(TConstBonusListPtr other) const
{
// The idea here is to avoid changing active bonusList while it can be read by a different thread.
// Because such use of shared ptr is not thread safe
// So to avoid this we change the second offline instance and swap active index
auto newCurrent = 1 - currentBonusListIndex;
bonusList[newCurrent] = other;
currentBonusListIndex = newCurrent;
}
TConstBonusListPtr CBonusProxy::getBonusList() const TConstBonusListPtr CBonusProxy::getBonusList() const
{ {
if(target->getTreeVersion() != bonusListCachedLast || !bonusList) auto needUpdateBonusList = [&]() -> bool
{ {
//TODO: support limiters return target->getTreeVersion() != bonusListCachedLast || !bonusList[currentBonusListIndex];
bonusList = target->getAllBonuses(selector, Selector::all); };
bonusListCachedLast = target->getTreeVersion();
// avoid locking if everything is up-to-date
if(needUpdateBonusList())
{
boost::lock_guard<boost::mutex>lock(swapGuard);
if(needUpdateBonusList())
{
//TODO: support limiters
swapBonusList(target->getAllBonuses(selector, Selector::all));
bonusListCachedLast = target->getTreeVersion();
}
} }
return bonusList;
return bonusList[currentBonusListIndex];
} }
const BonusList * CBonusProxy::operator->() const const BonusList * CBonusProxy::operator->() const

View File

@@ -84,7 +84,10 @@ protected:
CSelector selector; CSelector selector;
const IBonusBearer * target; const IBonusBearer * target;
mutable int64_t bonusListCachedLast; mutable int64_t bonusListCachedLast;
mutable TConstBonusListPtr bonusList; mutable TConstBonusListPtr bonusList[2];
mutable int currentBonusListIndex;
mutable boost::mutex swapGuard;
void swapBonusList(TConstBonusListPtr other) const;
}; };
class DLL_LINKAGE CTotalsProxy : public CBonusProxy class DLL_LINKAGE CTotalsProxy : public CBonusProxy