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:
committed by
Andrii Danylchenko
parent
b97e5817ce
commit
fa9a420f99
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user