Add timestamp to notifications of rendering engine and avoid race conditions in ASRangeControllerBeta

- Accurately remove notification observer
This commit is contained in:
Huy Nguyen 2016-02-04 13:59:43 -08:00
parent 3c135788cb
commit fda9efafa6
3 changed files with 22 additions and 9 deletions

View File

@ -30,6 +30,7 @@
NSInteger const ASDefaultDrawingPriority = ASDefaultTransactionPriority;
NSString * const ASRenderingEngineDidDisplayScheduledNodesNotification = @"ASRenderingEngineDidDisplayScheduledNodes";
NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp = @"ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp";
@interface _ASDisplayNodePosition : NSObject
@ -276,12 +277,14 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
ASDN::MutexLocker l(displaySchedulerLock);
displayScheduled = NO;
NSSet *displayingNodes = [nodesToDisplay copy];
CFAbsoluteTime timestamp = CFAbsoluteTimeGetCurrent();
nodesToDisplay = nil;
for (ASDisplayNode *node in displayingNodes) {
[node __recursivelyTriggerDisplayAndBlock:NO];
}
[[NSNotificationCenter defaultCenter] postNotificationName:ASRenderingEngineDidDisplayScheduledNodesNotification
object:nil];
object:displayingNodes
userInfo:@{ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp: [NSNumber numberWithDouble:timestamp]}];
});
}
}

View File

@ -27,6 +27,7 @@
NSSet<NSIndexPath *> *_allPreviousIndexPaths;
ASLayoutRangeMode _currentRangeMode;
BOOL _didRegisterForNotifications;
CFAbsoluteTime _pendingDisplayNodesTimestamp;
}
@end
@ -48,7 +49,7 @@
- (void)dealloc
{
if (_didRegisterForNotifications) {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] removeObserver:self name:ASRenderingEngineDidDisplayScheduledNodesNotification object:nil];
}
}
@ -243,7 +244,11 @@
}
}
}
if (_didRegisterForNotifications) {
_pendingDisplayNodesTimestamp = CFAbsoluteTimeGetCurrent();
}
_rangeIsValid = YES;
_queuedRangeUpdate = NO;
@ -280,7 +285,7 @@
currentRangeMode:_currentRangeMode];
if (_currentRangeMode != nextRangeMode) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(scheduledNodesDidDisplay)
selector:@selector(scheduledNodesDidDisplay:)
name:ASRenderingEngineDidDisplayScheduledNodesNotification
object:nil];
_didRegisterForNotifications = YES;
@ -288,12 +293,16 @@
}
}
- (void)scheduledNodesDidDisplay
- (void)scheduledNodesDidDisplay:(NSNotification *)notification
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
_didRegisterForNotifications = NO;
[self scheduleRangeUpdate];
CFAbsoluteTime notificationTimestamp = ((NSNumber *)[notification.userInfo objectForKey:ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp]).doubleValue;
if (_pendingDisplayNodesTimestamp < notificationTimestamp) {
// The rendering engine has processed all the nodes this range controller scheduled. Let's schedule a range update
[[NSNotificationCenter defaultCenter] removeObserver:self name:ASRenderingEngineDidDisplayScheduledNodesNotification object:nil];
_didRegisterForNotifications = NO;
[self scheduleRangeUpdate];
}
}
#pragma mark - Cell node view handling

View File

@ -38,6 +38,7 @@ typedef NS_OPTIONS(NSUInteger, ASDisplayNodeMethodOverrides)
@class _ASDisplayNodePosition;
FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayScheduledNodesNotification;
FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp;
// Allow 2^n increments of begin disabling hierarchy notifications
#define VISIBILITY_NOTIFICATIONS_DISABLED_BITS 4