Skip to content

Commit

Permalink
[ASDataController] Clean up (TextureGroup#443)
Browse files Browse the repository at this point in the history
* Clean up ASDataController
- Parameters passed to ASDataControllerCompletionBlock are no longer used. Remove them.
- The value returned by _allocateNodesFromElements:andLayout:completion is not used. Remove it.
- Elements are not allocated and measured in batches anymore. Remove the code that does batch allocation.
- Remove RETURN_IF_NO_DATASOURCE. It's used only once and is not worth it.

* Remove +parallelProcessorCount

* Update CHANGELOG
  • Loading branch information
nguyenhuy authored and bernieperez committed Apr 25, 2018
1 parent 250d7b2 commit ccc8287
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 64 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- Fix a crash where scrolling a table view after entering editing mode could lead to bad internal states in the table. [Huy Nguyen](https://github.com/nguyenhuy) [#416](https://github.com/TextureGroup/Texture/pull/416/)
- Fix a crash in collection view that occurs if batch updates are performed while scrolling [Huy Nguyen](https://github.com/nguyenhuy) [#378](https://github.com/TextureGroup/Texture/issues/378)
- Some improvements in ASCollectionView [Huy Nguyen](https://github.com/nguyenhuy) [#407](https://github.com/TextureGroup/Texture/pull/407)
- Small refactors in ASDataController [Huy Nguyen](https://github.com/TextureGroup/Texture/pull/443) [#443](https://github.com/TextureGroup/Texture/pull/443)

##2.3.4
- [Yoga] Rewrite YOGA_TREE_CONTIGUOUS mode with improved behavior and cleaner integration [Scott Goodson](https://github.com/appleguy)
Expand Down
97 changes: 33 additions & 64 deletions Source/Details/ASDataController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,8 @@
//#define LOG(...) NSLog(__VA_ARGS__)
#define LOG(...)

#define RETURN_IF_NO_DATASOURCE(val) if (_dataSource == nil) { return val; }
#define ASSERT_ON_EDITING_QUEUE ASDisplayNodeAssertNotNil(dispatch_get_specific(&kASDataControllerEditingQueueKey), @"%@ must be called on the editing transaction queue.", NSStringFromSelector(_cmd))

const static NSUInteger kASDataControllerSizingCountPerProcessor = 5;
const static char * kASDataControllerEditingQueueKey = "kASDataControllerEditingQueueKey";
const static char * kASDataControllerEditingQueueContext = "kASDataControllerEditingQueueContext";

Expand Down Expand Up @@ -123,18 +121,6 @@ - (instancetype)initWithDataSource:(id<ASDataControllerSource>)dataSource node:(
return self;
}

+ (NSUInteger)parallelProcessorCount
{
static NSUInteger parallelProcessorCount;

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
parallelProcessorCount = [[NSProcessInfo processInfo] activeProcessorCount];
});

return parallelProcessorCount;
}

- (id<ASDataControllerLayoutDelegate>)layoutDelegate
{
ASDisplayNodeAssertMainThread();
Expand All @@ -151,34 +137,47 @@ - (void)setLayoutDelegate:(id<ASDataControllerLayoutDelegate>)layoutDelegate

#pragma mark - Cell Layout

- (void)batchAllocateNodesFromElements:(NSArray<ASCollectionElement *> *)elements batchSize:(NSInteger)batchSize batchCompletion:(ASDataControllerCompletionBlock)batchCompletionHandler
- (void)_allocateNodesFromElements:(NSArray<ASCollectionElement *> *)elements completion:(ASDataControllerCompletionBlock)completionHandler
{
ASSERT_ON_EDITING_QUEUE;

if (elements.count == 0 || _dataSource == nil) {
batchCompletionHandler();

NSUInteger nodeCount = elements.count;
__weak id<ASDataControllerSource> weakDataSource = _dataSource;
if (nodeCount == 0 || weakDataSource == nil) {
completionHandler();
return;
}

ASSignpostStart(ASSignpostDataControllerBatch);

if (batchSize == 0) {
batchSize = [[ASDataController class] parallelProcessorCount] * kASDataControllerSizingCountPerProcessor;
}
NSUInteger count = elements.count;

// Processing in batches
for (NSUInteger i = 0; i < count; i += batchSize) {
NSRange batchedRange = NSMakeRange(i, MIN(count - i, batchSize));
NSArray<ASCollectionElement *> *batchedElements = [elements subarrayWithRange:batchedRange];
{
as_activity_create_for_scope("Data controller batch");
[self _allocateNodesFromElements:batchedElements];
}
batchCompletionHandler();
{
as_activity_create_for_scope("Data controller batch");

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
ASDispatchApply(nodeCount, queue, 0, ^(size_t i) {
__strong id<ASDataControllerSource> strongDataSource = weakDataSource;
if (strongDataSource == nil) {
return;
}

// Allocate the node.
ASCollectionElement *context = elements[i];
ASCellNode *node = context.node;
if (node == nil) {
ASDisplayNodeAssertNotNil(node, @"Node block created nil node; %@, %@", self, strongDataSource);
node = [[ASCellNode alloc] init]; // Fallback to avoid crash for production apps.
}

// Layout the node if the size range is valid.
ASSizeRange sizeRange = context.constrainedSize;
if (ASSizeRangeHasSignificantArea(sizeRange)) {
[self _layoutNode:node withConstrainedSize:sizeRange];
}
});
}

ASSignpostEndCustom(ASSignpostDataControllerBatch, self, 0, (_dataSource != nil ? ASSignpostColorDefault : ASSignpostColorRed));
completionHandler();
ASSignpostEndCustom(ASSignpostDataControllerBatch, self, 0, (weakDataSource != nil ? ASSignpostColorDefault : ASSignpostColorRed));
}

/**
Expand All @@ -193,36 +192,6 @@ - (void)_layoutNode:(ASCellNode *)node withConstrainedSize:(ASSizeRange)constrai
node.frame = frame;
}

// TODO Is returned array still needed? Can it be removed?
- (void)_allocateNodesFromElements:(NSArray<ASCollectionElement *> *)elements
{
ASSERT_ON_EDITING_QUEUE;

NSUInteger nodeCount = elements.count;
if (!nodeCount || _dataSource == nil) {
return;
}

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
ASDispatchApply(nodeCount, queue, 0, ^(size_t i) {
RETURN_IF_NO_DATASOURCE();

// Allocate the node.
ASCollectionElement *context = elements[i];
ASCellNode *node = context.node;
if (node == nil) {
ASDisplayNodeAssertNotNil(node, @"Node block created nil node; %@, %@", self, self.dataSource);
node = [[ASCellNode alloc] init]; // Fallback to avoid crash for production apps.
}

// Layout the node if the size range is valid.
ASSizeRange sizeRange = context.constrainedSize;
if (ASSizeRangeHasSignificantArea(sizeRange)) {
[self _layoutNode:node withConstrainedSize:sizeRange];
}
});
}

#pragma mark - Data Source Access (Calling _dataSource)

- (NSArray<NSIndexPath *> *)_allIndexPathsForItemsOfKind:(NSString *)kind inSections:(NSIndexSet *)sections
Expand Down Expand Up @@ -592,7 +561,7 @@ - (void)updateWithChangeSet:(_ASHierarchyChangeSet *)changeSet
NSArray<ASCollectionElement *> *elementsToProcess = ASArrayByFlatMapping(newMap,
ASCollectionElement *element,
(element.nodeIfAllocated.calculatedLayout == nil ? element : nil));
[self batchAllocateNodesFromElements:elementsToProcess batchSize:elementsToProcess.count batchCompletion:completion];
[self _allocateNodesFromElements:elementsToProcess completion:completion];
}
});

Expand Down

0 comments on commit ccc8287

Please sign in to comment.