|
|
@@ -17,8 +17,7 @@
|
|
|
|
|
|
VCMI_LIB_NAMESPACE_BEGIN
|
|
|
|
|
|
-std::atomic<int64_t> CBonusSystemNode::treeChanged(1);
|
|
|
-constexpr bool CBonusSystemNode::cachingEnabled = true;
|
|
|
+constexpr bool cachingEnabled = true;
|
|
|
|
|
|
std::shared_ptr<Bonus> CBonusSystemNode::getLocalBonus(const CSelector & selector)
|
|
|
{
|
|
|
@@ -97,11 +96,11 @@ void CBonusSystemNode::getAllBonusesRec(BonusList &out, const CSelector & select
|
|
|
|
|
|
TConstBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr) const
|
|
|
{
|
|
|
- if (CBonusSystemNode::cachingEnabled)
|
|
|
+ if (cachingEnabled)
|
|
|
{
|
|
|
// If a bonus system request comes with a caching string then look up in the map if there are any
|
|
|
// pre-calculated bonus results. Limiters can't be cached so they have to be calculated.
|
|
|
- if (cachedLast == treeChanged && !cachingStr.empty())
|
|
|
+ if (cachedLast == nodeChanged && !cachingStr.empty())
|
|
|
{
|
|
|
RequestsMap::const_accessor accessor;
|
|
|
|
|
|
@@ -114,7 +113,7 @@ TConstBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, co
|
|
|
//Perform bonus selection
|
|
|
auto ret = std::make_shared<BonusList>();
|
|
|
|
|
|
- if (cachedLast == treeChanged)
|
|
|
+ if (cachedLast == nodeChanged)
|
|
|
{
|
|
|
// Cached bonuses are up-to-date - use shared/read access and compute results
|
|
|
std::shared_lock lock(sync);
|
|
|
@@ -125,7 +124,7 @@ TConstBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, co
|
|
|
// If the bonus system tree changes(state of a single node or the relations to each other) then
|
|
|
// cache all bonus objects. Selector objects doesn't matter.
|
|
|
std::lock_guard lock(sync);
|
|
|
- if (cachedLast == treeChanged)
|
|
|
+ if (cachedLast == nodeChanged)
|
|
|
{
|
|
|
// While our thread was waiting, another one have updated bonus tree. Use cached bonuses.
|
|
|
cachedBonuses.getBonuses(*ret, selector, limit);
|
|
|
@@ -140,7 +139,7 @@ TConstBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, co
|
|
|
getAllBonusesRec(allBonuses, Selector::all);
|
|
|
limitBonuses(allBonuses, cachedBonuses);
|
|
|
cachedBonuses.stackBonuses();
|
|
|
- cachedLast = treeChanged;
|
|
|
+ cachedLast = nodeChanged;
|
|
|
cachedBonuses.getBonuses(*ret, selector, limit);
|
|
|
}
|
|
|
}
|
|
|
@@ -155,7 +154,7 @@ TConstBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, co
|
|
|
accessor->second.first = cachedLast;
|
|
|
}
|
|
|
else
|
|
|
- cachedRequests.emplace(cachingStr, std::pair<int64_t, TBonusListPtr>{ cachedLast, ret });
|
|
|
+ cachedRequests.emplace(cachingStr, std::pair<int32_t, TBonusListPtr>{ cachedLast, ret });
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
|
@@ -187,8 +186,6 @@ std::shared_ptr<Bonus> CBonusSystemNode::getUpdatedBonus(const std::shared_ptr<B
|
|
|
}
|
|
|
|
|
|
CBonusSystemNode::CBonusSystemNode(bool isHypotetic):
|
|
|
- bonuses(true),
|
|
|
- exportedBonuses(true),
|
|
|
nodeType(UNKNOWN),
|
|
|
cachedLast(0),
|
|
|
isHypotheticNode(isHypotetic)
|
|
|
@@ -196,8 +193,6 @@ CBonusSystemNode::CBonusSystemNode(bool isHypotetic):
|
|
|
}
|
|
|
|
|
|
CBonusSystemNode::CBonusSystemNode(ENodeTypes NodeType):
|
|
|
- bonuses(true),
|
|
|
- exportedBonuses(true),
|
|
|
nodeType(NodeType),
|
|
|
cachedLast(0),
|
|
|
isHypotheticNode(false)
|
|
|
@@ -227,10 +222,11 @@ void CBonusSystemNode::attachTo(CBonusSystemNode & parent)
|
|
|
if(!parent.actsAsBonusSourceOnly())
|
|
|
newRedDescendant(parent);
|
|
|
|
|
|
- parent.newChildAttached(*this);
|
|
|
+ assert(!vstd::contains(parent.children, this));
|
|
|
+ parent.children.push_back(this);
|
|
|
}
|
|
|
|
|
|
- CBonusSystemNode::treeHasChanged();
|
|
|
+ nodeHasChanged();
|
|
|
}
|
|
|
|
|
|
void CBonusSystemNode::attachToSource(const CBonusSystemNode & parent)
|
|
|
@@ -244,7 +240,7 @@ void CBonusSystemNode::attachToSource(const CBonusSystemNode & parent)
|
|
|
parent.newRedDescendant(*this);
|
|
|
}
|
|
|
|
|
|
- CBonusSystemNode::treeHasChanged();
|
|
|
+ nodeHasChanged();
|
|
|
}
|
|
|
|
|
|
void CBonusSystemNode::detachFrom(CBonusSystemNode & parent)
|
|
|
@@ -271,9 +267,15 @@ void CBonusSystemNode::detachFrom(CBonusSystemNode & parent)
|
|
|
|
|
|
if(!isHypothetic())
|
|
|
{
|
|
|
- parent.childDetached(*this);
|
|
|
+ if(vstd::contains(parent.children, this))
|
|
|
+ parent.children -= this;
|
|
|
+ else
|
|
|
+ {
|
|
|
+ logBonus->error("Error on Detach. Node %s (nodeType=%d) is not a child of %s (nodeType=%d)"
|
|
|
+ , nodeShortInfo(), nodeType, parent.nodeShortInfo(), parent.nodeType);
|
|
|
+ }
|
|
|
}
|
|
|
- CBonusSystemNode::treeHasChanged();
|
|
|
+ nodeHasChanged();
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -297,7 +299,7 @@ void CBonusSystemNode::detachFromSource(const CBonusSystemNode & parent)
|
|
|
, nodeShortInfo(), nodeType, parent.nodeShortInfo(), parent.nodeType);
|
|
|
}
|
|
|
|
|
|
- CBonusSystemNode::treeHasChanged();
|
|
|
+ nodeHasChanged();
|
|
|
}
|
|
|
|
|
|
void CBonusSystemNode::removeBonusesRecursive(const CSelector & s)
|
|
|
@@ -333,7 +335,6 @@ void CBonusSystemNode::addNewBonus(const std::shared_ptr<Bonus>& b)
|
|
|
assert(!vstd::contains(exportedBonuses, b));
|
|
|
exportedBonuses.push_back(b);
|
|
|
exportBonus(b);
|
|
|
- CBonusSystemNode::treeHasChanged();
|
|
|
}
|
|
|
|
|
|
void CBonusSystemNode::accumulateBonus(const std::shared_ptr<Bonus>& b)
|
|
|
@@ -349,10 +350,14 @@ void CBonusSystemNode::removeBonus(const std::shared_ptr<Bonus>& b)
|
|
|
{
|
|
|
exportedBonuses -= b;
|
|
|
if(b->propagator)
|
|
|
+ {
|
|
|
unpropagateBonus(b);
|
|
|
+ }
|
|
|
else
|
|
|
+ {
|
|
|
bonuses -= b;
|
|
|
- CBonusSystemNode::treeHasChanged();
|
|
|
+ nodeHasChanged();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void CBonusSystemNode::removeBonuses(const CSelector & selector)
|
|
|
@@ -385,6 +390,7 @@ void CBonusSystemNode::propagateBonus(const std::shared_ptr<Bonus> & b, const CB
|
|
|
: b;
|
|
|
bonuses.push_back(propagated);
|
|
|
logBonus->trace("#$# %s #propagated to# %s", propagated->Description(nullptr), nodeName());
|
|
|
+ nodeHasChanged();
|
|
|
}
|
|
|
|
|
|
TNodes lchildren;
|
|
|
@@ -402,11 +408,11 @@ void CBonusSystemNode::unpropagateBonus(const std::shared_ptr<Bonus> & b)
|
|
|
else
|
|
|
logBonus->warn("Attempt to remove #$# %s, which is not propagated to %s", b->Description(nullptr), nodeName());
|
|
|
|
|
|
- bonuses.remove_if([b](const auto & bonus)
|
|
|
+ bonuses.remove_if([this, b](const auto & bonus)
|
|
|
{
|
|
|
if (bonus->propagationUpdater && bonus->propagationUpdater == b->propagationUpdater)
|
|
|
{
|
|
|
- treeHasChanged();
|
|
|
+ nodeHasChanged();
|
|
|
return true;
|
|
|
}
|
|
|
return false;
|
|
|
@@ -419,23 +425,6 @@ void CBonusSystemNode::unpropagateBonus(const std::shared_ptr<Bonus> & b)
|
|
|
pname->unpropagateBonus(b);
|
|
|
}
|
|
|
|
|
|
-void CBonusSystemNode::newChildAttached(CBonusSystemNode & child)
|
|
|
-{
|
|
|
- assert(!vstd::contains(children, &child));
|
|
|
- children.push_back(&child);
|
|
|
-}
|
|
|
-
|
|
|
-void CBonusSystemNode::childDetached(CBonusSystemNode & child)
|
|
|
-{
|
|
|
- if(vstd::contains(children, &child))
|
|
|
- children -= &child;
|
|
|
- else
|
|
|
- {
|
|
|
- logBonus->error("Error on Detach. Node %s (nodeType=%d) is not a child of %s (nodeType=%d)"
|
|
|
- , child.nodeShortInfo(), child.nodeType, nodeShortInfo(), nodeType);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
void CBonusSystemNode::detachFromAll()
|
|
|
{
|
|
|
while(!parentsToPropagate.empty())
|
|
|
@@ -558,11 +547,14 @@ void CBonusSystemNode::getRedAncestors(TCNodes &out) const
|
|
|
void CBonusSystemNode::exportBonus(const std::shared_ptr<Bonus> & b)
|
|
|
{
|
|
|
if(b->propagator)
|
|
|
+ {
|
|
|
propagateBonus(b, *this);
|
|
|
+ }
|
|
|
else
|
|
|
+ {
|
|
|
bonuses.push_back(b);
|
|
|
-
|
|
|
- CBonusSystemNode::treeHasChanged();
|
|
|
+ nodeHasChanged();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void CBonusSystemNode::exportBonuses()
|
|
|
@@ -631,14 +623,27 @@ void CBonusSystemNode::limitBonuses(const BonusList &allBonuses, BonusList &out)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void CBonusSystemNode::treeHasChanged()
|
|
|
+void CBonusSystemNode::nodeHasChanged()
|
|
|
{
|
|
|
- treeChanged++;
|
|
|
+ static std::atomic<int32_t> globalCounter = 1;
|
|
|
+
|
|
|
+ invalidateChildrenNodes(++globalCounter);
|
|
|
+}
|
|
|
+
|
|
|
+void CBonusSystemNode::invalidateChildrenNodes(int32_t changeCounter)
|
|
|
+{
|
|
|
+ if (nodeChanged == changeCounter)
|
|
|
+ return;
|
|
|
+
|
|
|
+ nodeChanged = changeCounter;
|
|
|
+
|
|
|
+ for(CBonusSystemNode * child : children)
|
|
|
+ child->invalidateChildrenNodes(changeCounter);
|
|
|
}
|
|
|
|
|
|
-int64_t CBonusSystemNode::getTreeVersion() const
|
|
|
+int32_t CBonusSystemNode::getTreeVersion() const
|
|
|
{
|
|
|
- return treeChanged;
|
|
|
+ return nodeChanged;
|
|
|
}
|
|
|
|
|
|
VCMI_LIB_NAMESPACE_END
|