Merge pull request #1765 from facebook/AHLockingPassOne

[ASDisplayNode] Resolve Deadlock Caused By removeFromSupernode
This commit is contained in:
Adlai Holler
2016-06-17 13:58:10 -07:00
committed by GitHub
3 changed files with 78 additions and 28 deletions

View File

@@ -1515,40 +1515,36 @@ static NSInteger incrementIfFound(NSInteger i) {
[subnode __setSupernode:nil];
}
// NOTE: You must not called this method while holding the receiver's property lock. This may cause deadlocks.
- (void)removeFromSupernode
{
ASDisplayNodeAssertThreadAffinity(self);
BOOL shouldRemoveFromSuperviewOrSuperlayer = NO;
_propertyLock.lock();
__weak ASDisplayNode *supernode = _supernode;
__weak UIView *view = _view;
__weak CALayer *layer = _layer;
BOOL layerBacked = _flags.layerBacked;
_propertyLock.unlock();
{
ASDN::MutexLocker l(_propertyLock);
if (!_supernode)
return;
if (supernode == nil) {
return;
}
[supernode _removeSubnode:self];
if (self.nodeLoaded && supernode.nodeLoaded) {
// Check to ensure that our view or layer is actually inside of our supernode; otherwise, don't remove it.
// Though _ASDisplayView decouples the supernode if it is inserted inside another view hierarchy, this is
// more difficult to guarantee with _ASDisplayLayer because CoreAnimation doesn't have a -didMoveToSuperlayer.
if (self.nodeLoaded && _supernode.nodeLoaded) {
if (_flags.layerBacked || _supernode.layerBacked) {
shouldRemoveFromSuperviewOrSuperlayer = (_layer.superlayer == _supernode.layer);
} else {
shouldRemoveFromSuperviewOrSuperlayer = (_view.superview == _supernode.view);
}
}
}
// Do this before removing the view from the hierarchy, as the node will clear its supernode pointer when its view is removed from the hierarchy.
// This call may result in the object being destroyed.
[_supernode _removeSubnode:self];
if (shouldRemoveFromSuperviewOrSuperlayer) {
ASPerformBlockOnMainThread(^{
ASDN::MutexLocker l(_propertyLock);
if (_flags.layerBacked) {
[_layer removeFromSuperlayer];
if (layerBacked || supernode.layerBacked) {
if (layer.superlayer == supernode.layer) {
[layer removeFromSuperlayer];
}
} else {
[_view removeFromSuperview];
if (view.superview == supernode.view) {
[view removeFromSuperview];
}
}
});
}

View File

@@ -48,9 +48,12 @@
{
ASDN::MutexLocker l(_propertyLock);
[self calculateSubnodeOperationsIfNeeded];
for (NSUInteger i = 0; i < [_insertedSubnodes count]; i++) {
NSUInteger i = 0;
for (ASDisplayNode *node in _insertedSubnodes) {
NSUInteger p = _insertedSubnodePositions[i];
[_node insertSubnode:_insertedSubnodes[i] atIndex:p];
[_node insertSubnode:node atIndex:p];
i += 1;
}
}
@@ -58,8 +61,8 @@
{
ASDN::MutexLocker l(_propertyLock);
[self calculateSubnodeOperationsIfNeeded];
for (NSUInteger i = 0; i < [_removedSubnodes count]; i++) {
[_removedSubnodes[i] removeFromSupernode];
for (ASDisplayNode *subnode in _removedSubnodes) {
[subnode removeFromSupernode];
}
}