Skip to content

Commit

Permalink
[ASImageNode] Fix a threading issue which can cause a display comple…
Browse files Browse the repository at this point in the history
…tion block to never be executed (TextureGroup#1148)

- Clear _displayCompletionBlock while we still have the node's instance lock. Because it may not be the same block by the time the lock is reacquired. In other words, it can happen that another thread sets a new display block after this thread releases the lock but before it reacquires it. And we don't want to clear out the new block.
- Reduce a lock/unlock pair which should help perf a tiny bit.
  • Loading branch information
nguyenhuy authored and mikezucc committed Nov 7, 2018
1 parent b58d626 commit f2cdbee
Showing 1 changed file with 9 additions and 7 deletions.
16 changes: 9 additions & 7 deletions Source/ASImageNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -533,8 +533,15 @@ - (void)displayDidFinish
[super displayDidFinish];

__instanceLock__.lock();
void (^displayCompletionBlock)(BOOL canceled) = _displayCompletionBlock;
UIImage *image = _image;
void (^displayCompletionBlock)(BOOL canceled) = _displayCompletionBlock;
BOOL shouldPerformDisplayCompletionBlock = (image && displayCompletionBlock);

// Clear the ivar now. The block is retained and will be executed shortly.
if (shouldPerformDisplayCompletionBlock) {
_displayCompletionBlock = nil;
}

BOOL hasDebugLabel = (_debugLabelNode != nil);
__instanceLock__.unlock();

Expand All @@ -556,13 +563,8 @@ - (void)displayDidFinish
}

// If we've got a block to perform after displaying, do it.
if (image && displayCompletionBlock) {

if (shouldPerformDisplayCompletionBlock) {
displayCompletionBlock(NO);

__instanceLock__.lock();
_displayCompletionBlock = nil;
__instanceLock__.unlock();
}
}

Expand Down

0 comments on commit f2cdbee

Please sign in to comment.