Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make objects conform to NSLocking #851

Merged
merged 10 commits into from
Mar 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions AsyncDisplayKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,6 @@
DBDB83971C6E879900D0098C /* ASPagerFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = DBDB83931C6E879900D0098C /* ASPagerFlowLayout.m */; };
DE4843DC1C93EAC100A1F33B /* ASLayoutTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = E52405B41C8FEF16004DC8E7 /* ASLayoutTransition.h */; settings = {ATTRIBUTES = (Private, ); }; };
DE6EA3231C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
DE7EF4F81DFF77720082B84A /* ASDisplayNode+FrameworkSubclasses.h in Headers */ = {isa = PBXBuildFile; fileRef = DE7EF4F71DFF77720082B84A /* ASDisplayNode+FrameworkSubclasses.h */; settings = {ATTRIBUTES = (Private, ); }; };
DE84918D1C8FFF2B003D89E9 /* ASRunLoopQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 81EE384D1C8E94F000456208 /* ASRunLoopQueue.h */; settings = {ATTRIBUTES = (Public, ); }; };
DE84918E1C8FFF9F003D89E9 /* ASRunLoopQueue.mm in Sources */ = {isa = PBXBuildFile; fileRef = 81EE384E1C8E94F000456208 /* ASRunLoopQueue.mm */; };
DE8BEAC21C2DF3FC00D57C12 /* ASDelegateProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = DE8BEABF1C2DF3FC00D57C12 /* ASDelegateProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
Expand Down Expand Up @@ -933,7 +932,6 @@
DBDB83921C6E879900D0098C /* ASPagerFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPagerFlowLayout.h; sourceTree = "<group>"; };
DBDB83931C6E879900D0098C /* ASPagerFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPagerFlowLayout.m; sourceTree = "<group>"; };
DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASDisplayNode+FrameworkPrivate.h"; sourceTree = "<group>"; };
DE7EF4F71DFF77720082B84A /* ASDisplayNode+FrameworkSubclasses.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASDisplayNode+FrameworkSubclasses.h"; sourceTree = "<group>"; };
DE8BEABF1C2DF3FC00D57C12 /* ASDelegateProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDelegateProxy.h; sourceTree = "<group>"; };
DE8BEAC01C2DF3FC00D57C12 /* ASDelegateProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDelegateProxy.m; sourceTree = "<group>"; };
DEC146B41C37A16A004A0EE7 /* ASCollectionInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASCollectionInternal.h; path = Details/ASCollectionInternal.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1441,7 +1439,6 @@
058D0A09195D050800B7D73C /* ASDisplayNode+DebugTiming.h */,
058D0A0A195D050800B7D73C /* ASDisplayNode+DebugTiming.mm */,
DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */,
DE7EF4F71DFF77720082B84A /* ASDisplayNode+FrameworkSubclasses.h */,
058D0A0B195D050800B7D73C /* ASDisplayNode+UIViewBridge.mm */,
058D0A0C195D050800B7D73C /* ASDisplayNodeInternal.h */,
6959433D1D70815300B0EE1F /* ASDisplayNodeLayout.h */,
Expand Down Expand Up @@ -1849,7 +1846,6 @@
34EFC7691B701CE100AD841F /* ASLayoutElement.h in Headers */,
698DFF471E36B7E9002891F1 /* ASLayoutSpecUtilities.h in Headers */,
9C70F20D1CDBE9CB007D6C76 /* ASDefaultPlayButton.h in Headers */,
DE7EF4F81DFF77720082B84A /* ASDisplayNode+FrameworkSubclasses.h in Headers */,
CCCCCCD51EC3EF060087FE10 /* ASTextDebugOption.h in Headers */,
CC034A091E60BEB400626263 /* ASDisplayNode+Convenience.h in Headers */,
254C6B7E1BF94DF4003EC431 /* ASTextKitTailTruncater.h in Headers */,
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
- Fix ASTextNode2 handling background color incorrectly. [Adlai Holler](https://github.com/Adlai-Holler) [#831](https://github.com/TextureGroup/Texture/pull/831/)
- [NoCopyRendering] Improved performance & fixed image memory not being tagged in Instruments. [Adlai Holler](https://github.com/Adlai-Holler) [#833](https://github.com/TextureGroup/Texture/pull/833/)
- Use `NS_RETURNS_RETAINED` macro to make our methods a tiny bit faster. [Adlai Holler](https://github.com/Adlai-Holler) [#843](https://github.com/TextureGroup/Texture/pull/843/)
- `ASDisplayNode, ASLayoutSpec, and ASLayoutElementStyle` now conform to `NSLocking`. They act as recursive locks. Useful locking macros have been added as `ASThread.h`. Subclasses / client code can lock these objects but should be careful as usual when dealing with locks. [Adlai Holler](https://github.com/Adlai-Holler)

## 2.6
- [Xcode 9] Updated to require Xcode 9 (to fix warnings) [Garrett Moon](https://github.com/garrettmoon)
Expand Down
58 changes: 29 additions & 29 deletions Source/ASButtonNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#import <AsyncDisplayKit/ASButtonNode.h>
#import <AsyncDisplayKit/ASStackLayoutSpec.h>
#import <AsyncDisplayKit/ASThread.h>
#import <AsyncDisplayKit/ASDisplayNode+FrameworkSubclasses.h>
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
#import <AsyncDisplayKit/ASBackgroundLayoutSpec.h>
#import <AsyncDisplayKit/ASInsetLayoutSpec.h>
#import <AsyncDisplayKit/ASAbsoluteLayoutSpec.h>
Expand Down Expand Up @@ -161,7 +161,7 @@ - (void)setDisplaysAsynchronously:(BOOL)displaysAsynchronously

- (void)updateImage
{
__instanceLock__.lock();
[self lock];

UIImage *newImage;
if (self.enabled == NO && _disabledImage) {
Expand All @@ -178,18 +178,18 @@ - (void)updateImage

if ((_imageNode != nil || newImage != nil) && newImage != self.imageNode.image) {
_imageNode.image = newImage;
__instanceLock__.unlock();
[self unlock];

[self setNeedsLayout];
return;
}

__instanceLock__.unlock();
[self unlock];
}

- (void)updateTitle
{
__instanceLock__.lock();
[self lock];

NSAttributedString *newTitle;
if (self.enabled == NO && _disabledAttributedTitle) {
Expand All @@ -207,19 +207,19 @@ - (void)updateTitle
// Calling self.titleNode is essential here because _titleNode is lazily created by the getter.
if ((_titleNode != nil || newTitle.length > 0) && [self.titleNode.attributedText isEqualToAttributedString:newTitle] == NO) {
_titleNode.attributedText = newTitle;
__instanceLock__.unlock();
[self unlock];

self.accessibilityLabel = _titleNode.accessibilityLabel;
[self setNeedsLayout];
return;
}

__instanceLock__.unlock();
[self unlock];
}

- (void)updateBackgroundImage
{
__instanceLock__.lock();
[self lock];

UIImage *newImage;
if (self.enabled == NO && _disabledBackgroundImage) {
Expand All @@ -236,25 +236,25 @@ - (void)updateBackgroundImage

if ((_backgroundImageNode != nil || newImage != nil) && newImage != self.backgroundImageNode.image) {
_backgroundImageNode.image = newImage;
__instanceLock__.unlock();
[self unlock];

[self setNeedsLayout];
return;
}

__instanceLock__.unlock();
[self unlock];
}

- (CGFloat)contentSpacing
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
return _contentSpacing;
}

- (void)setContentSpacing:(CGFloat)contentSpacing
{
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
if (contentSpacing == _contentSpacing) {
return;
}
Expand All @@ -267,14 +267,14 @@ - (void)setContentSpacing:(CGFloat)contentSpacing

- (BOOL)laysOutHorizontally
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
return _laysOutHorizontally;
}

- (void)setLaysOutHorizontally:(BOOL)laysOutHorizontally
{
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
if (laysOutHorizontally == _laysOutHorizontally) {
return;
}
Expand All @@ -287,49 +287,49 @@ - (void)setLaysOutHorizontally:(BOOL)laysOutHorizontally

- (ASVerticalAlignment)contentVerticalAlignment
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
return _contentVerticalAlignment;
}

- (void)setContentVerticalAlignment:(ASVerticalAlignment)contentVerticalAlignment
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
_contentVerticalAlignment = contentVerticalAlignment;
}

- (ASHorizontalAlignment)contentHorizontalAlignment
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
return _contentHorizontalAlignment;
}

- (void)setContentHorizontalAlignment:(ASHorizontalAlignment)contentHorizontalAlignment
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
_contentHorizontalAlignment = contentHorizontalAlignment;
}

- (UIEdgeInsets)contentEdgeInsets
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
return _contentEdgeInsets;
}

- (void)setContentEdgeInsets:(UIEdgeInsets)contentEdgeInsets
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
_contentEdgeInsets = contentEdgeInsets;
}

- (ASButtonNodeImageAlignment)imageAlignment
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
return _imageAlignment;
}

- (void)setImageAlignment:(ASButtonNodeImageAlignment)imageAlignment
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
_imageAlignment = imageAlignment;
}

Expand All @@ -349,7 +349,7 @@ - (void)setTitle:(NSString *)title withFont:(UIFont *)font withColor:(UIColor *)

- (NSAttributedString *)attributedTitleForState:(UIControlState)state
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
switch (state) {
case UIControlStateNormal:
return _normalAttributedTitle;
Expand All @@ -374,7 +374,7 @@ - (NSAttributedString *)attributedTitleForState:(UIControlState)state
- (void)setAttributedTitle:(NSAttributedString *)title forState:(UIControlState)state
{
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
switch (state) {
case UIControlStateNormal:
_normalAttributedTitle = [title copy];
Expand Down Expand Up @@ -406,7 +406,7 @@ - (void)setAttributedTitle:(NSAttributedString *)title forState:(UIControlState)

- (UIImage *)imageForState:(UIControlState)state
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
switch (state) {
case UIControlStateNormal:
return _normalImage;
Expand All @@ -431,7 +431,7 @@ - (UIImage *)imageForState:(UIControlState)state
- (void)setImage:(UIImage *)image forState:(UIControlState)state
{
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
switch (state) {
case UIControlStateNormal:
_normalImage = image;
Expand Down Expand Up @@ -463,7 +463,7 @@ - (void)setImage:(UIImage *)image forState:(UIControlState)state

- (UIImage *)backgroundImageForState:(UIControlState)state
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
switch (state) {
case UIControlStateNormal:
return _normalBackgroundImage;
Expand All @@ -488,7 +488,7 @@ - (UIImage *)backgroundImageForState:(UIControlState)state
- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state
{
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
switch (state) {
case UIControlStateNormal:
_normalBackgroundImage = image;
Expand Down Expand Up @@ -525,7 +525,7 @@ - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
ASLayoutSpec *spec;
ASStackLayoutSpec *stack = [[ASStackLayoutSpec alloc] init];
{
ASDN::MutexLocker l(__instanceLock__);
ASLockScopeSelf();
stack.direction = _laysOutHorizontally ? ASStackLayoutDirectionHorizontal : ASStackLayoutDirectionVertical;
stack.spacing = _contentSpacing;
stack.horizontalAlignment = _contentHorizontalAlignment;
Expand Down
58 changes: 28 additions & 30 deletions Source/ASControlNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@
@interface ASControlNode ()
{
@private
ASDN::RecursiveMutex _controlLock;

// Control Attributes
BOOL _enabled;
BOOL _highlighted;
Expand Down Expand Up @@ -298,7 +296,7 @@ - (void)addTarget:(id)target action:(SEL)action forControlEvents:(ASControlNodeE
// ASControlNode cannot be layer backed if adding a target
ASDisplayNodeAssert(!self.isLayerBacked, @"ASControlNode is layer backed, will never be able to call target in target:action: pair.");

ASDN::MutexLocker l(_controlLock);
ASLockScopeSelf();

if (!_controlEventDispatchTable) {
_controlEventDispatchTable = [[NSMutableDictionary alloc] initWithCapacity:kASControlNodeEventDispatchTableInitialCapacity]; // enough to handle common types without re-hashing the dictionary when adding entries.
Expand Down Expand Up @@ -352,7 +350,7 @@ - (NSArray *)actionsForTarget:(id)target forControlEvent:(ASControlNodeEvent)con
NSParameterAssert(target);
NSParameterAssert(controlEvent != 0 && controlEvent != ASControlNodeEventAllEvents);

ASDN::MutexLocker l(_controlLock);
ASLockScopeSelf();

// Grab the event target action array for this event.
NSMutableArray *eventTargetActionArray = _controlEventDispatchTable[_ASControlNodeEventKeyForControlEvent(controlEvent)];
Expand All @@ -374,7 +372,7 @@ - (NSArray *)actionsForTarget:(id)target forControlEvent:(ASControlNodeEvent)con

- (NSSet *)allTargets
{
ASDN::MutexLocker l(_controlLock);
ASLockScopeSelf();

NSMutableSet *targets = [[NSMutableSet alloc] init];

Expand All @@ -393,7 +391,7 @@ - (void)removeTarget:(id)target action:(SEL)action forControlEvents:(ASControlNo
{
NSParameterAssert(controlEventMask != 0);

ASDN::MutexLocker l(_controlLock);
ASLockScopeSelf();

// Enumerate the events in the mask, removing the target-action pair for each control event included in controlEventMask.
_ASEnumerateControlEventsIncludedInMaskWithBlock(controlEventMask, ^
Expand Down Expand Up @@ -435,31 +433,31 @@ - (void)sendActionsForControlEvents:(ASControlNodeEvent)controlEvents withEvent:

NSMutableArray *resolvedEventTargetActionArray = [[NSMutableArray<ASControlTargetAction *> alloc] init];

_controlLock.lock();

// Enumerate the events in the mask, invoking the target-action pairs for each.
_ASEnumerateControlEventsIncludedInMaskWithBlock(controlEvents, ^
(ASControlNodeEvent controlEvent)
{
// Iterate on each target action pair
for (ASControlTargetAction *targetAction in _controlEventDispatchTable[_ASControlNodeEventKeyForControlEvent(controlEvent)]) {
ASControlTargetAction *resolvedTargetAction = [[ASControlTargetAction alloc] init];
resolvedTargetAction.action = targetAction.action;
resolvedTargetAction.target = targetAction.target;

// NSNull means that a nil target was set, so start at self and travel the responder chain
if (!resolvedTargetAction.target && targetAction.createdWithNoTarget) {
// if the target cannot perform the action, travel the responder chain to try to find something that does
resolvedTargetAction.target = [self.view targetForAction:resolvedTargetAction.action withSender:self];
}

if (resolvedTargetAction.target) {
[resolvedEventTargetActionArray addObject:resolvedTargetAction];
{
ASLockScopeSelf();

// Enumerate the events in the mask, invoking the target-action pairs for each.
_ASEnumerateControlEventsIncludedInMaskWithBlock(controlEvents, ^
(ASControlNodeEvent controlEvent)
{
// Iterate on each target action pair
for (ASControlTargetAction *targetAction in _controlEventDispatchTable[_ASControlNodeEventKeyForControlEvent(controlEvent)]) {
ASControlTargetAction *resolvedTargetAction = [[ASControlTargetAction alloc] init];
resolvedTargetAction.action = targetAction.action;
resolvedTargetAction.target = targetAction.target;

// NSNull means that a nil target was set, so start at self and travel the responder chain
if (!resolvedTargetAction.target && targetAction.createdWithNoTarget) {
// if the target cannot perform the action, travel the responder chain to try to find something that does
resolvedTargetAction.target = [self.view targetForAction:resolvedTargetAction.action withSender:self];
}

if (resolvedTargetAction.target) {
[resolvedEventTargetActionArray addObject:resolvedTargetAction];
}
}
}
});

_controlLock.unlock();
});
}

//We don't want to hold the lock while calling out, we could potentially walk up the ownership tree causing a deadlock.
#pragma clang diagnostic push
Expand Down
5 changes: 2 additions & 3 deletions Source/ASDisplayNode+Layout.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@

#import <AsyncDisplayKit/ASDisplayNodeExtras.h>
#import <AsyncDisplayKit/ASDisplayNodeInternal.h>
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
#import <AsyncDisplayKit/ASInternalHelpers.h>
#import <AsyncDisplayKit/ASLayout.h>
#import <AsyncDisplayKit/ASLayoutElementStylePrivate.h>
#import <AsyncDisplayKit/ASLog.h>

#import <AsyncDisplayKit/ASDisplayNode+FrameworkSubclasses.h>

#pragma mark -
#pragma mark - ASDisplayNode (ASLayoutElement)

@implementation ASDisplayNode (ASLayoutElement)
Expand Down
Loading