We will revert #1023. The current solution introduces problems if we are unlocking before calling _completePendingLayoutTransition. _completePendingLayoutTransition needs to be happening in one transaction if called from _u_measureNodeWithBoundsIfNecessary.
This commit is contained in:
Michael Schneider 2018-11-03 12:32:15 -07:00 committed by Huy Nguyen
parent ecfc7835da
commit a34f45355e
2 changed files with 134 additions and 135 deletions

View File

@ -296,8 +296,6 @@ ASLayoutElementStyleExtensibilityForwarding
{ {
ASAssertUnlocked(__instanceLock__); ASAssertUnlocked(__instanceLock__);
BOOL isInLayoutPendingState = NO;
{
ASDN::MutexLocker l(__instanceLock__); ASDN::MutexLocker l(__instanceLock__);
// Check if we are a subnode in a layout transition. // Check if we are a subnode in a layout transition.
// In this case no measurement is needed as it's part of the layout transition // In this case no measurement is needed as it's part of the layout transition
@ -410,11 +408,9 @@ ASLayoutElementStyleExtensibilityForwarding
_pendingLayoutTransition = [[ASLayoutTransition alloc] initWithNode:self _pendingLayoutTransition = [[ASLayoutTransition alloc] initWithNode:self
pendingLayout:nextLayout pendingLayout:nextLayout
previousLayout:_calculatedDisplayNodeLayout]; previousLayout:_calculatedDisplayNodeLayout];
isInLayoutPendingState = ASHierarchyStateIncludesLayoutPending(_hierarchyState);
}
// If a parent is currently executing a layout transition, perform our layout application after it. // If a parent is currently executing a layout transition, perform our layout application after it.
if (isInLayoutPendingState == NO) { if (ASHierarchyStateIncludesLayoutPending(_hierarchyState) == NO) {
// If no transition, apply our new layout immediately (common case). // If no transition, apply our new layout immediately (common case).
[self _completePendingLayoutTransition]; [self _completePendingLayoutTransition];
} }
@ -872,18 +868,12 @@ ASLayoutElementStyleExtensibilityForwarding
*/ */
- (void)_completePendingLayoutTransition - (void)_completePendingLayoutTransition
{ {
ASAssertUnlocked(__instanceLock__); __instanceLock__.lock();
ASLayoutTransition *pendingLayoutTransition = _pendingLayoutTransition;
ASLayoutTransition *pendingLayoutTransition; __instanceLock__.unlock();
{
ASDN::MutexLocker l(__instanceLock__);
pendingLayoutTransition = _pendingLayoutTransition;
if (pendingLayoutTransition != nil) {
[self _locked_setCalculatedDisplayNodeLayout:pendingLayoutTransition.pendingLayout];
}
}
if (pendingLayoutTransition != nil) { if (pendingLayoutTransition != nil) {
[self _setCalculatedDisplayNodeLayout:pendingLayoutTransition.pendingLayout];
[self _completeLayoutTransition:pendingLayoutTransition]; [self _completeLayoutTransition:pendingLayoutTransition];
[self _pendingLayoutTransitionDidComplete]; [self _pendingLayoutTransitionDidComplete];
} }
@ -903,7 +893,8 @@ ASLayoutElementStyleExtensibilityForwarding
// Trampoline to the main thread if necessary // Trampoline to the main thread if necessary
if (ASDisplayNodeThreadIsMain() || layoutTransition.isSynchronous == NO) { if (ASDisplayNodeThreadIsMain() || layoutTransition.isSynchronous == NO) {
// Committing the layout transition will result in subnode insertions and removals, both of which must be called without the lock held // Committing the layout transition will result in subnode insertions and removals, both of which must be called without the lock held
ASAssertUnlocked(__instanceLock__); // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204
// ASAssertUnlocked(__instanceLock__);
[layoutTransition commitTransition]; [layoutTransition commitTransition];
} else { } else {
// Subnode insertions and removals need to happen always on the main thread if at least one subnode is already loaded // Subnode insertions and removals need to happen always on the main thread if at least one subnode is already loaded
@ -963,7 +954,8 @@ ASLayoutElementStyleExtensibilityForwarding
#endif #endif
// Subclass hook // Subclass hook
ASAssertUnlocked(__instanceLock__); // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204
// ASAssertUnlocked(__instanceLock__);
[self calculatedLayoutDidChange]; [self calculatedLayoutDidChange];
// Grab lock after calling out to subclass // Grab lock after calling out to subclass

View File

@ -2215,7 +2215,8 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
- (void)_insertSubnode:(ASDisplayNode *)subnode atSubnodeIndex:(NSInteger)subnodeIndex sublayerIndex:(NSInteger)sublayerIndex andRemoveSubnode:(ASDisplayNode *)oldSubnode - (void)_insertSubnode:(ASDisplayNode *)subnode atSubnodeIndex:(NSInteger)subnodeIndex sublayerIndex:(NSInteger)sublayerIndex andRemoveSubnode:(ASDisplayNode *)oldSubnode
{ {
ASDisplayNodeAssertThreadAffinity(self); ASDisplayNodeAssertThreadAffinity(self);
ASAssertUnlocked(__instanceLock__); // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204
// ASAssertUnlocked(__instanceLock__);
as_log_verbose(ASNodeLog(), "Insert subnode %@ at index %zd of %@ and remove subnode %@", subnode, subnodeIndex, self, oldSubnode); as_log_verbose(ASNodeLog(), "Insert subnode %@ at index %zd of %@ and remove subnode %@", subnode, subnodeIndex, self, oldSubnode);
@ -2431,7 +2432,8 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
- (void)_insertSubnode:(ASDisplayNode *)subnode belowSubnode:(ASDisplayNode *)below - (void)_insertSubnode:(ASDisplayNode *)subnode belowSubnode:(ASDisplayNode *)below
{ {
ASDisplayNodeAssertThreadAffinity(self); ASDisplayNodeAssertThreadAffinity(self);
ASAssertUnlocked(__instanceLock__); // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204
// ASAssertUnlocked(__instanceLock__);
if (subnode == nil) { if (subnode == nil) {
ASDisplayNodeFailAssert(@"Cannot insert a nil subnode"); ASDisplayNodeFailAssert(@"Cannot insert a nil subnode");
@ -2495,7 +2497,8 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
- (void)_insertSubnode:(ASDisplayNode *)subnode aboveSubnode:(ASDisplayNode *)above - (void)_insertSubnode:(ASDisplayNode *)subnode aboveSubnode:(ASDisplayNode *)above
{ {
ASDisplayNodeAssertThreadAffinity(self); ASDisplayNodeAssertThreadAffinity(self);
ASAssertUnlocked(__instanceLock__); // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204
// ASAssertUnlocked(__instanceLock__);
if (subnode == nil) { if (subnode == nil) {
ASDisplayNodeFailAssert(@"Cannot insert a nil subnode"); ASDisplayNodeFailAssert(@"Cannot insert a nil subnode");
@ -2557,7 +2560,8 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
- (void)_insertSubnode:(ASDisplayNode *)subnode atIndex:(NSInteger)idx - (void)_insertSubnode:(ASDisplayNode *)subnode atIndex:(NSInteger)idx
{ {
ASDisplayNodeAssertThreadAffinity(self); ASDisplayNodeAssertThreadAffinity(self);
ASAssertUnlocked(__instanceLock__); // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204
// ASAssertUnlocked(__instanceLock__);
if (subnode == nil) { if (subnode == nil) {
ASDisplayNodeFailAssert(@"Cannot insert a nil subnode"); ASDisplayNodeFailAssert(@"Cannot insert a nil subnode");
@ -2594,7 +2598,8 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
- (void)_removeSubnode:(ASDisplayNode *)subnode - (void)_removeSubnode:(ASDisplayNode *)subnode
{ {
ASDisplayNodeAssertThreadAffinity(self); ASDisplayNodeAssertThreadAffinity(self);
ASAssertUnlocked(__instanceLock__); // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204
// ASAssertUnlocked(__instanceLock__);
// Don't call self.supernode here because that will retain/autorelease the supernode. This method -_removeSupernode: is often called while tearing down a node hierarchy, and the supernode in question might be in the middle of its -dealloc. The supernode is never messaged, only compared by value, so this is safe. // Don't call self.supernode here because that will retain/autorelease the supernode. This method -_removeSupernode: is often called while tearing down a node hierarchy, and the supernode in question might be in the middle of its -dealloc. The supernode is never messaged, only compared by value, so this is safe.
// The particular issue that triggers this edge case is when a node calls -removeFromSupernode on a subnode from within its own -dealloc method. // The particular issue that triggers this edge case is when a node calls -removeFromSupernode on a subnode from within its own -dealloc method.
@ -2620,7 +2625,8 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
- (void)_removeFromSupernode - (void)_removeFromSupernode
{ {
ASDisplayNodeAssertThreadAffinity(self); ASDisplayNodeAssertThreadAffinity(self);
ASAssertUnlocked(__instanceLock__); // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204
// ASAssertUnlocked(__instanceLock__);
__instanceLock__.lock(); __instanceLock__.lock();
__weak ASDisplayNode *supernode = _supernode; __weak ASDisplayNode *supernode = _supernode;
@ -2634,7 +2640,8 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
- (void)_removeFromSupernodeIfEqualTo:(ASDisplayNode *)supernode - (void)_removeFromSupernodeIfEqualTo:(ASDisplayNode *)supernode
{ {
ASDisplayNodeAssertThreadAffinity(self); ASDisplayNodeAssertThreadAffinity(self);
ASAssertUnlocked(__instanceLock__); // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204
// ASAssertUnlocked(__instanceLock__);
__instanceLock__.lock(); __instanceLock__.lock();