mirror of
https://github.com/HackPlan/AsyncDisplayKit.git
synced 2026-05-16 16:01:00 +08:00
Order-of-magnitude speedup in handling of "disable visibility notifications"
Before, it was expensive to check this value, even though it was rarely set. Now the cost is moved to setting the value, and is made very cheap to check with _hierarchyState.
This commit is contained in:
@@ -1251,44 +1251,41 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)__visibilityNotificationsDisabled
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return _flags.visibilityNotificationsDisabled > 0;
|
||||
}
|
||||
|
||||
- (void)__incrementVisibilityNotificationsDisabled
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
const size_t maxVisibilityIncrement = (1ULL<<VISIBILITY_NOTIFICATIONS_DISABLED_BITS) - 1ULL;
|
||||
ASDisplayNodeAssert(_flags.visibilityNotificationsDisabled < maxVisibilityIncrement, @"Oops, too many increments of the visibility notifications API");
|
||||
if (_flags.visibilityNotificationsDisabled < maxVisibilityIncrement)
|
||||
if (_flags.visibilityNotificationsDisabled < maxVisibilityIncrement) {
|
||||
_flags.visibilityNotificationsDisabled++;
|
||||
}
|
||||
if (_flags.visibilityNotificationsDisabled == 1) {
|
||||
// Must have just transitioned from 0 to 1. Notify all subnodes that we are in a disabled state.
|
||||
[self enterHierarchyState:ASHierarchyStateTransitioningSupernodes];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)__decrementVisibilityNotificationsDisabled
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
ASDisplayNodeAssert(_flags.visibilityNotificationsDisabled > 0, @"Can't decrement past 0");
|
||||
if (_flags.visibilityNotificationsDisabled > 0)
|
||||
if (_flags.visibilityNotificationsDisabled > 0) {
|
||||
_flags.visibilityNotificationsDisabled--;
|
||||
}
|
||||
if (_flags.visibilityNotificationsDisabled == 0) {
|
||||
// Must have just transitioned from 1 to 0. Notify all subnodes that we are no longer in a disabled state.
|
||||
// FIXME: This system should be revisited when refactoring and consolidating the implementation of the
|
||||
// addSubnode: and insertSubnode:... methods. As implemented, though logically irrelevant for expected use cases,
|
||||
// multiple nodes in the subtree below may have a non-zero visibilityNotification count and still have
|
||||
// the ASHierarchyState bit cleared (the only value checked when reading this state).
|
||||
[self exitHierarchyState:ASHierarchyStateTransitioningSupernodes];
|
||||
}
|
||||
}
|
||||
|
||||
// This uses the layer hieararchy for safety. Who knows what people might do and it would be bad to have visibilty out of sync
|
||||
- (BOOL)__selfOrParentHasVisibilityNotificationsDisabled
|
||||
{
|
||||
CALayer *layer = _layer;
|
||||
do {
|
||||
ASDisplayNode *node = ASLayerToDisplayNode(layer);
|
||||
if (node) {
|
||||
if (node->_flags.visibilityNotificationsDisabled) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
layer = layer.superlayer;
|
||||
} while (layer);
|
||||
|
||||
return NO;
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return (_hierarchyState & ASHierarchyStateTransitioningSupernodes);
|
||||
}
|
||||
|
||||
- (void)__enterHierarchy
|
||||
|
||||
@@ -7,12 +7,10 @@
|
||||
*/
|
||||
|
||||
#import "ASDisplayNode+DebugTiming.h"
|
||||
|
||||
#import "ASDisplayNodeInternal.h"
|
||||
|
||||
@implementation ASDisplayNode (DebugTiming)
|
||||
|
||||
|
||||
#if TIME_DISPLAYNODE_OPS
|
||||
- (NSTimeInterval)debugTimeToCreateView
|
||||
{
|
||||
@@ -83,6 +81,4 @@
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@@ -37,14 +37,17 @@
|
||||
typedef NS_OPTIONS(NSUInteger, ASHierarchyState)
|
||||
{
|
||||
/** The node may or may not have a supernode, but no supernode has a special hierarchy-influencing option enabled. */
|
||||
ASHierarchyStateNormal = 0,
|
||||
ASHierarchyStateNormal = 0,
|
||||
/** The node has a supernode with .shouldRasterizeDescendants = YES.
|
||||
Note: the root node of the rasterized subtree (the one with the property set on it) will NOT have this state set. */
|
||||
ASHierarchyStateRasterized = 1 << 0,
|
||||
ASHierarchyStateRasterized = 1 << 0,
|
||||
/** The node or one of its supernodes is managed by a class like ASRangeController. Most commonly, these nodes are
|
||||
ASCellNode objects or a subnode of one, and are used in ASTableView or ASCollectionView.
|
||||
These nodes also recieve regular updates to the .interfaceState property with more detailed status information. */
|
||||
ASHierarchyStateRangeManaged = 1 << 1,
|
||||
ASHierarchyStateRangeManaged = 1 << 1,
|
||||
/** Down-propogated version of _flags.visibilityNotificationsDisabled. This flag is very rarely set, but by having it
|
||||
locally available to nodes, they do not have to walk up supernodes at the critical points it is checked. */
|
||||
ASHierarchyStateTransitioningSupernodes = 1 << 2
|
||||
};
|
||||
|
||||
@interface ASDisplayNode () <_ASDisplayLayerDelegate>
|
||||
|
||||
@@ -105,7 +105,6 @@ typedef NS_OPTIONS(NSUInteger, ASDisplayNodeMethodOverrides)
|
||||
NSTimeInterval _debugTimeToAddSubnodeViews;
|
||||
NSTimeInterval _debugTimeForDidLoad;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
+ (void)scheduleNodeForDisplay:(ASDisplayNode *)node;
|
||||
|
||||
Reference in New Issue
Block a user