Makes Yoga threadsafed: #791
Reference in New Issue
Block a user
No description provided.
Delete Branch "yoga_thread_safety_master"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Issue ref: https://github.com/facebook/yoga/issues/769
Problem
gNodeInstanceCount
,gConfigInstanceCount
,gCurrentGenerationCount
,gDepth
are global variables inYoga.cpp
. They are not safe when using multithreading.My idea
atomic
forgNodeInstanceCount
andgConfigInstanceCount
because of counting instances only.gCurrentGenerationCount
andgDepth
in root node for multithreading.My solution
gNodeInstanceCount
andgConfigInstanceCount
gCurrentGenerationCount
andgDepth
are stored inYGNode
.Thank @rockerhieu for support.
I was very recently concerned by Yoga thread safety and saw your PR. Thanks for your contribution.
I see your PR sitting dormant for some time. I'd love to see this topic addressed, so I thought to provide a review with some suggestions for improvement, in the hope we can have an update merged.
If you lack time, or would like some help in refactoring the PR, let me know as I'm happy to help.
@@ -273,0 +275,4 @@
YGNodeRef pRoot = nullptr;
public:
uint32_t gCurrentGenerationCount = 0;
We can probably reduce the storage here to just 16-bits (
uint16_t
), saving 2 bytes overhead per node here, and inYGLayout
(saving another 4 bytes). Do we really need to track more than 65,535 generations?Since this is now a member, we probably shouldn't use the "g" (global) prefix. It might also be a good idea to make it private, with inlined access via:
@@ -273,0 +276,4 @@
public:
uint32_t gCurrentGenerationCount = 0;
uint32_t gDepth = 0;
We can avoid storing
gDepth
in every node (4 bytes overhead) by:gDepth
(perhaps renamed to justdepth
, again avoiding the global naming prefix) between function calls that stem fromYGNodeCalculateLayout
.YGNodeCalculateLayout
, passdepth
as value 0, to indicate the root depth.gPrintChanges
is true), you could further place the increment/decrement in an if-statement that gets optimized out by the compiler whengPrintChanges == false
, after further refactoring the latter to be const (or#define
'd).Similarly, we can additionally pass the generation via function calls as above, to avoid the need for a pointer from each node to the tree root, saving another 8 bytes. I suspect the approach used in this PR also breaks cloning, which uses a "copy on write" scheme. In this PR, the pointer to the root is overwritten by
YGNodeClone
immediately on all children when cloning; but now the cloned nodes are no-longer "shared": we would ideally need the cloned children to point to each of their tree roots; but that becomes awkward as we'd have to manage 1:M pointers, where M is the number of distinct clones. (This doesn't say how we'd then know which of the M pointers to use when performing layout on a cloned subtree; that would be difficult.)By removing the pointer to the tree root we can also drop the new method
setChildRoot
which performs a full subtree traversal that can be expensive.@jpap unfortunately nokia6686 left the team several months ago, we are trying to pick up what he left and carry out the pull request with https://github.com/facebook/yoga/pull/852.
It looks like this was succeeded by https://github.com/facebook/yoga/pull/852 which was merged. Going to close this PR.
Pull request closed