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:
parent
b97e5817ce
commit
fa9a420f99
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user