Skip to content

Commit 2baa943

Browse files
authored
Have node and controller share lock (#1227)
* Have node and controller share lock * Do it different * Restore prior method order * Maybe store the reference * Try that
1 parent 8029632 commit 2baa943

File tree

2 files changed

+31
-20
lines changed

2 files changed

+31
-20
lines changed

Source/ASNodeController+Beta.h

+9-4
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,21 @@
1010
#import <AsyncDisplayKit/ASDisplayNode.h>
1111
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h> // for ASInterfaceState protocol
1212

13+
NS_ASSUME_NONNULL_BEGIN
14+
1315
/* ASNodeController is currently beta and open to change in the future */
1416
@interface ASNodeController<__covariant DisplayNodeType : ASDisplayNode *>
15-
: NSObject <ASInterfaceStateDelegate, NSLocking>
17+
: NSObject <ASInterfaceStateDelegate, ASLocking>
1618

17-
@property (nonatomic, strong /* may be weak! */) DisplayNodeType node;
19+
@property (strong, readonly /* may be weak! */) DisplayNodeType node;
1820

1921
// Until an ASNodeController can be provided in place of an ASCellNode, some apps may prefer to have
2022
// nodes keep their controllers alive (and a weak reference from controller to node)
2123

2224
@property (nonatomic) BOOL shouldInvertStrongReference;
2325

24-
- (void)loadNode;
26+
// called on an arbitrary thread by the framework. You do not call this. Return a new node instance.
27+
- (DisplayNodeType)createNode;
2528

2629
// for descriptions see <ASInterfaceState> definition
2730
- (void)nodeDidLoad ASDISPLAYNODE_REQUIRES_SUPER;
@@ -48,6 +51,8 @@
4851

4952
@interface ASDisplayNode (ASNodeController)
5053

51-
@property(nonatomic, readonly) ASNodeController *nodeController;
54+
@property(nullable, readonly) ASNodeController *nodeController;
5255

5356
@end
57+
58+
NS_ASSUME_NONNULL_END

Source/ASNodeController+Beta.mm

+22-16
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,27 @@ @implementation ASNodeController
1818
{
1919
ASDisplayNode *_strongNode;
2020
__weak ASDisplayNode *_weakNode;
21-
ASDN::RecursiveMutex __instanceLock__;
21+
ASDN::Mutex _nodeLock;
2222
}
2323

24-
- (void)loadNode
24+
- (ASDisplayNode *)createNode
2525
{
26-
ASLockScopeSelf();
27-
self.node = [[ASDisplayNode alloc] init];
26+
return [[ASDisplayNode alloc] init];
2827
}
2928

3029
- (ASDisplayNode *)node
3130
{
32-
ASLockScopeSelf();
33-
if (_node == nil) {
34-
[self loadNode];
31+
ASDN::MutexLocker l(_nodeLock);
32+
ASDisplayNode *node = _node;
33+
if (!node) {
34+
node = [self createNode];
35+
if (!node) {
36+
ASDisplayNodeCFailAssert(@"Returned nil from -createNode.");
37+
node = [[ASDisplayNode alloc] init];
38+
}
39+
[self setupReferencesWithNode:node];
3540
}
36-
return _node;
41+
return node;
3742
}
3843

3944
- (void)setupReferencesWithNode:(ASDisplayNode *)node
@@ -53,12 +58,6 @@ - (void)setupReferencesWithNode:(ASDisplayNode *)node
5358
[node addInterfaceStateDelegate:self];
5459
}
5560

56-
- (void)setNode:(ASDisplayNode *)node
57-
{
58-
ASLockScopeSelf();
59-
[self setupReferencesWithNode:node];
60-
}
61-
6261
- (void)setShouldInvertStrongReference:(BOOL)shouldInvertStrongReference
6362
{
6463
ASLockScopeSelf();
@@ -93,12 +92,19 @@ - (void)hierarchyDisplayDidFinish {}
9392

9493
- (void)lock
9594
{
96-
__instanceLock__.lock();
95+
[self.node lock];
9796
}
9897

9998
- (void)unlock
10099
{
101-
__instanceLock__.unlock();
100+
// Since the node was already locked on this thread, we don't need to call our accessor or take our lock.
101+
ASDisplayNodeAssertNotNil(_node, @"Node deallocated while locked.");
102+
[_node unlock];
103+
}
104+
105+
- (BOOL)tryLock
106+
{
107+
return [self.node tryLock];
102108
}
103109

104110
@end

0 commit comments

Comments
 (0)