Make sure -_completePendingLayoutTransition is called without the node's instance lock #trivial (#1023)

This is because committing the layout transition (aka `-_completeLayoutTransition:`) results in subnode insertions and removals which must be called lock-free.
This commit is contained in:
Huy Nguyen 2018-07-12 11:26:26 -07:00 committed by GitHub
parent 5ffcd405c6
commit 814fc382c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -296,6 +296,9 @@ ASLayoutElementStyleExtensibilityForwarding
- (void)_u_measureNodeWithBoundsIfNecessary:(CGRect)bounds - (void)_u_measureNodeWithBoundsIfNecessary:(CGRect)bounds
{ {
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock); ASDisplayNodeAssertLockUnownedByCurrentThread(__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
@ -400,9 +403,11 @@ 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 (ASHierarchyStateIncludesLayoutPending(_hierarchyState) == NO) { if (isInLayoutPendingState == 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];
} }
@ -860,12 +865,18 @@ ASLayoutElementStyleExtensibilityForwarding
*/ */
- (void)_completePendingLayoutTransition - (void)_completePendingLayoutTransition
{ {
__instanceLock__.lock(); ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock);
ASLayoutTransition *pendingLayoutTransition = _pendingLayoutTransition;
__instanceLock__.unlock(); ASLayoutTransition *pendingLayoutTransition = nil;
{
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];
} }