Makes Yoga threadsafed:
- Uses <atomic> for gNodeInstanceCount & gConfigInstanceCount because of counting instance only. - Store gCurrentGenerationCount & gDepth in root node for multithreading.
This commit is contained in:
@@ -255,14 +255,17 @@ void YGNode::setNextChild(YGNodeRef nextChild) {
|
||||
|
||||
void YGNode::replaceChild(YGNodeRef child, uint32_t index) {
|
||||
children_[index] = child;
|
||||
setChildRoot(child);
|
||||
}
|
||||
|
||||
void YGNode::replaceChild(YGNodeRef oldChild, YGNodeRef newChild) {
|
||||
std::replace(children_.begin(), children_.end(), oldChild, newChild);
|
||||
setChildRoot(newChild);
|
||||
}
|
||||
|
||||
void YGNode::insertChild(YGNodeRef child, uint32_t index) {
|
||||
children_.insert(children_.begin() + index, child);
|
||||
setChildRoot(child);
|
||||
}
|
||||
|
||||
void YGNode::setConfig(YGConfigRef config) {
|
||||
@@ -770,3 +773,15 @@ bool YGNode::isLayoutTreeEqualToNode(const YGNode& node) const {
|
||||
}
|
||||
return isLayoutTreeEqual;
|
||||
}
|
||||
|
||||
YGNodeRef YGNode::getRoot() {
|
||||
if (pRoot == nullptr) pRoot = this;
|
||||
return pRoot;
|
||||
}
|
||||
|
||||
void YGNode::setChildRoot(YGNodeRef node) {
|
||||
node->pRoot = getRoot();
|
||||
for (auto child: node->children_) {
|
||||
setChildRoot(child);
|
||||
}
|
||||
}
|
@@ -183,4 +183,13 @@ struct YGNode {
|
||||
bool isNodeFlexible();
|
||||
bool didUseLegacyFlag();
|
||||
bool isLayoutTreeEqualToNode(const YGNode& node) const;
|
||||
|
||||
private:
|
||||
YGNodeRef pRoot = nullptr;
|
||||
|
||||
public:
|
||||
uint32_t gCurrentGenerationCount = 0;
|
||||
uint32_t gDepth = 0;
|
||||
YGNodeRef getRoot();
|
||||
void setChildRoot(YGNodeRef node);
|
||||
};
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include "YGNode.h"
|
||||
#include "YGNodePrint.h"
|
||||
#include "Yoga-internal.h"
|
||||
#include <atomic>
|
||||
#ifdef _MSC_VER
|
||||
#include <float.h>
|
||||
|
||||
@@ -211,8 +212,8 @@ void YGNodeMarkDirtyAndPropogateToDescendants(const YGNodeRef node) {
|
||||
return node->markDirtyAndPropogateDownwards();
|
||||
}
|
||||
|
||||
int32_t gNodeInstanceCount = 0;
|
||||
int32_t gConfigInstanceCount = 0;
|
||||
std::atomic<int32_t> gNodeInstanceCount(0);
|
||||
std::atomic<int32_t> gConfigInstanceCount(0);
|
||||
|
||||
WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config) {
|
||||
const YGNodeRef node = new YGNode();
|
||||
@@ -243,6 +244,7 @@ YGNodeRef YGNodeClone(YGNodeRef oldNode) {
|
||||
oldNode->getConfig(),
|
||||
node != nullptr,
|
||||
"Could not allocate memory for node");
|
||||
oldNode->setChildRoot(node);
|
||||
gNodeInstanceCount++;
|
||||
node->setOwner(nullptr);
|
||||
return node;
|
||||
@@ -300,8 +302,8 @@ void YGNodeFree(const YGNodeRef node) {
|
||||
|
||||
static void YGConfigFreeRecursive(const YGNodeRef root) {
|
||||
if (root->getConfig() != nullptr) {
|
||||
gConfigInstanceCount--;
|
||||
delete root->getConfig();
|
||||
gConfigInstanceCount--;
|
||||
}
|
||||
// Delete configs recursively for childrens
|
||||
for (uint32_t i = 0; i < root->getChildrenCount(); ++i) {
|
||||
@@ -959,8 +961,6 @@ bool YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(const YGNodeRef node) {
|
||||
return node->getLayout().doesLegacyStretchFlagAffectsLayout;
|
||||
}
|
||||
|
||||
uint32_t gCurrentGenerationCount = 0;
|
||||
|
||||
bool YGLayoutNodeInternal(const YGNodeRef node,
|
||||
const float availableWidth,
|
||||
const float availableHeight,
|
||||
@@ -1219,8 +1219,7 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node,
|
||||
if (child->getLayout().computedFlexBasis.isUndefined() ||
|
||||
(YGConfigIsExperimentalFeatureEnabled(
|
||||
child->getConfig(), YGExperimentalFeatureWebFlexBasis) &&
|
||||
child->getLayout().computedFlexBasisGeneration !=
|
||||
gCurrentGenerationCount)) {
|
||||
child->getLayout().computedFlexBasisGeneration != node->getRoot()->gCurrentGenerationCount)) {
|
||||
const YGFloatOptional& paddingAndBorder = YGFloatOptional(
|
||||
YGNodePaddingAndBorderForAxis(child, mainAxis, ownerWidth));
|
||||
child->setLayoutComputedFlexBasis(
|
||||
@@ -1360,7 +1359,7 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node,
|
||||
child->getLayout().measuredDimensions[dim[mainAxis]],
|
||||
YGNodePaddingAndBorderForAxis(child, mainAxis, ownerWidth))));
|
||||
}
|
||||
child->setLayoutComputedFlexBasisGeneration(gCurrentGenerationCount);
|
||||
child->setLayoutComputedFlexBasisGeneration(node->getRoot()->gCurrentGenerationCount);
|
||||
}
|
||||
|
||||
static void YGNodeAbsoluteLayoutChild(const YGNodeRef node,
|
||||
@@ -1826,7 +1825,7 @@ static void YGNodeComputeFlexBasisForChildren(
|
||||
continue;
|
||||
}
|
||||
if (child == singleFlexChild) {
|
||||
child->setLayoutComputedFlexBasisGeneration(gCurrentGenerationCount);
|
||||
child->setLayoutComputedFlexBasisGeneration(node->getRoot()->gCurrentGenerationCount);
|
||||
child->setLayoutComputedFlexBasis(YGFloatOptional(0));
|
||||
} else {
|
||||
YGNodeComputeFlexBasisForChild(
|
||||
@@ -3343,7 +3342,6 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t gDepth = 0;
|
||||
bool gPrintTree = false;
|
||||
bool gPrintChanges = false;
|
||||
bool gPrintSkips = false;
|
||||
@@ -3514,10 +3512,10 @@ bool YGLayoutNodeInternal(const YGNodeRef node,
|
||||
const YGConfigRef config) {
|
||||
YGLayout* layout = &node->getLayout();
|
||||
|
||||
gDepth++;
|
||||
node->getRoot()->gDepth++;
|
||||
|
||||
const bool needToVisitNode =
|
||||
(node->isDirty() && layout->generationCount != gCurrentGenerationCount) ||
|
||||
(node->isDirty() && layout->generationCount != node->getRoot()->gCurrentGenerationCount) ||
|
||||
layout->lastOwnerDirection != ownerDirection;
|
||||
|
||||
if (needToVisitNode) {
|
||||
@@ -3609,7 +3607,7 @@ bool YGLayoutNodeInternal(const YGNodeRef node,
|
||||
layout->measuredDimensions[YGDimensionHeight] = cachedResults->computedHeight;
|
||||
|
||||
if (gPrintChanges && gPrintSkips) {
|
||||
YGLog(node, YGLogLevelVerbose, "%s%d.{[skipped] ", YGSpacer(gDepth), gDepth);
|
||||
YGLog(node, YGLogLevelVerbose, "%s%d.{[skipped] ", YGSpacer(node->getRoot()->gDepth), node->getRoot()->gDepth);
|
||||
if (node->getPrintFunc() != nullptr) {
|
||||
node->getPrintFunc()(node);
|
||||
}
|
||||
@@ -3631,8 +3629,8 @@ bool YGLayoutNodeInternal(const YGNodeRef node,
|
||||
node,
|
||||
YGLogLevelVerbose,
|
||||
"%s%d.{%s",
|
||||
YGSpacer(gDepth),
|
||||
gDepth,
|
||||
YGSpacer(node->getRoot()->gDepth),
|
||||
node->getRoot()->gDepth,
|
||||
needToVisitNode ? "*" : "");
|
||||
if (node->getPrintFunc() != nullptr) {
|
||||
node->getPrintFunc()(node);
|
||||
@@ -3664,8 +3662,8 @@ bool YGLayoutNodeInternal(const YGNodeRef node,
|
||||
node,
|
||||
YGLogLevelVerbose,
|
||||
"%s%d.}%s",
|
||||
YGSpacer(gDepth),
|
||||
gDepth,
|
||||
YGSpacer(node->getRoot()->gDepth),
|
||||
node->getRoot()->gDepth,
|
||||
needToVisitNode ? "*" : "");
|
||||
if (node->getPrintFunc() != nullptr) {
|
||||
node->getPrintFunc()(node);
|
||||
@@ -3722,8 +3720,8 @@ bool YGLayoutNodeInternal(const YGNodeRef node,
|
||||
node->setDirty(false);
|
||||
}
|
||||
|
||||
gDepth--;
|
||||
layout->generationCount = gCurrentGenerationCount;
|
||||
node->getRoot()->gDepth--;
|
||||
layout->generationCount = node->getRoot()->gCurrentGenerationCount;
|
||||
return (needToVisitNode || cachedResults == nullptr);
|
||||
}
|
||||
|
||||
@@ -3819,7 +3817,7 @@ void YGNodeCalculateLayout(
|
||||
// all dirty nodes at least once. Subsequent visits will be skipped if the
|
||||
// input
|
||||
// parameters don't change.
|
||||
gCurrentGenerationCount++;
|
||||
node->getRoot()->gCurrentGenerationCount++;
|
||||
node->resolveDimension();
|
||||
float width = YGUndefined;
|
||||
YGMeasureMode widthMeasureMode = YGMeasureModeUndefined;
|
||||
@@ -3899,7 +3897,7 @@ void YGNodeCalculateLayout(
|
||||
originalNode->resolveDimension();
|
||||
// Recursively mark nodes as dirty
|
||||
originalNode->markDirtyAndPropogateDownwards();
|
||||
gCurrentGenerationCount++;
|
||||
node->getRoot()->gCurrentGenerationCount++;
|
||||
// Rerun the layout, and calculate the diff
|
||||
originalNode->setAndPropogateUseLegacyFlag(false);
|
||||
if (YGLayoutNodeInternal(
|
||||
|
Reference in New Issue
Block a user