1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-13 13:18:43 +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;
if(sameNode || node.action == CGPathNode::ENodeAction::UNKNOWN || !node.actor->hero)
if(sameNode || node.action == CGPathNode::ENodeAction::UNKNOWN || !node.actor || !node.actor->hero)
{
continue;
}

View File

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

View File

@ -97,7 +97,9 @@ CBonusProxy::CBonusProxy(const IBonusBearer * Target, CSelector Selector)
: bonusListCachedLast(0),
target(Target),
selector(Selector),
bonusList()
bonusList(),
currentBonusListIndex(0),
swapGuard()
{
}
@ -106,27 +108,34 @@ CBonusProxy::CBonusProxy(const CBonusProxy & other)
: bonusListCachedLast(other.bonusListCachedLast),
target(other.target),
selector(other.selector),
bonusList(other.bonusList)
currentBonusListIndex(other.currentBonusListIndex),
swapGuard()
{
bonusList[currentBonusListIndex] = other.bonusList[currentBonusListIndex];
}
CBonusProxy::CBonusProxy(CBonusProxy && other)
: bonusListCachedLast(0),
target(other.target),
selector(),
bonusList()
bonusList(),
currentBonusListIndex(0),
swapGuard()
{
std::swap(bonusListCachedLast, other.bonusListCachedLast);
std::swap(selector, other.selector);
std::swap(bonusList, other.bonusList);
std::swap(currentBonusListIndex, other.currentBonusListIndex);
}
CBonusProxy & CBonusProxy::operator=(const CBonusProxy & other)
{
bonusListCachedLast = other.bonusListCachedLast;
boost::lock_guard<boost::mutex> lock(swapGuard);
selector = other.selector;
bonusList = other.bonusList;
swapBonusList(other.bonusList[other.currentBonusListIndex]);
bonusListCachedLast = other.bonusListCachedLast;
return *this;
}
@ -135,18 +144,42 @@ CBonusProxy & CBonusProxy::operator=(CBonusProxy && other)
std::swap(bonusListCachedLast, other.bonusListCachedLast);
std::swap(selector, other.selector);
std::swap(bonusList, other.bonusList);
std::swap(currentBonusListIndex, other.currentBonusListIndex);
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
{
if(target->getTreeVersion() != bonusListCachedLast || !bonusList)
auto needUpdateBonusList = [&]() -> bool
{
//TODO: support limiters
bonusList = target->getAllBonuses(selector, Selector::all);
bonusListCachedLast = target->getTreeVersion();
return target->getTreeVersion() != bonusListCachedLast || !bonusList[currentBonusListIndex];
};
// 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

View File

@ -84,7 +84,10 @@ protected:
CSelector selector;
const IBonusBearer * target;
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