Add a concurrent flag to ASStackLayoutSpec that is off by default (#3148)

This commit is contained in:
Huy Nguyen 2017-03-08 16:33:50 +00:00 committed by GitHub
parent 21953c97ef
commit dd8cac4414
4 changed files with 29 additions and 17 deletions

View File

@ -59,11 +59,14 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, assign) ASStackLayoutJustifyContent justifyContent; @property (nonatomic, assign) ASStackLayoutJustifyContent justifyContent;
/** Orientation of children along cross axis. Defaults to ASStackLayoutAlignItemsStretch */ /** Orientation of children along cross axis. Defaults to ASStackLayoutAlignItemsStretch */
@property (nonatomic, assign) ASStackLayoutAlignItems alignItems; @property (nonatomic, assign) ASStackLayoutAlignItems alignItems;
//TODO documentation. Defaults to ASStackLayoutFlexWrapNoWrap /** Whether children are stacked into a single or multiple lines. Defaults to single line (ASStackLayoutFlexWrapNoWrap) */
@property (nonatomic, assign) ASStackLayoutFlexWrap flexWrap; @property (nonatomic, assign) ASStackLayoutFlexWrap flexWrap;
//TODO documentation. Defaults to ASStackLayoutAlignContentStart /** Orientation of lines along cross axis if there are multiple lines. Defaults to ASStackLayoutAlignContentStart */
@property (nonatomic, assign) ASStackLayoutAlignContent alignContent; @property (nonatomic, assign) ASStackLayoutAlignContent alignContent;
/** Whether this stack can dispatch to other threads, regardless of which thread it's running on */
@property (nonatomic, assign, getter=isConcurrent) BOOL concurrent;
- (instancetype)init; - (instancetype)init;
/** /**
@ -84,8 +87,9 @@ NS_ASSUME_NONNULL_BEGIN
@param spacing The spacing between the children @param spacing The spacing between the children
@param justifyContent If no children are flexible, this describes how to fill any extra space @param justifyContent If no children are flexible, this describes how to fill any extra space
@param alignItems Orientation of the children along the cross axis @param alignItems Orientation of the children along the cross axis
@param flexWrap Whether children are stacked into a single or multiple lines
@param alignContent Orientation of lines along cross axis if there are multiple lines
@param children ASLayoutElement children to be positioned. @param children ASLayoutElement children to be positioned.
TODO documentation flex wrap and align content
*/ */
+ (instancetype)stackLayoutSpecWithDirection:(ASStackLayoutDirection)direction + (instancetype)stackLayoutSpecWithDirection:(ASStackLayoutDirection)direction
spacing:(CGFloat)spacing spacing:(CGFloat)spacing

View File

@ -136,7 +136,7 @@
const ASStackLayoutSpecStyle style = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems, .flexWrap = _flexWrap, .alignContent = _alignContent}; const ASStackLayoutSpecStyle style = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems, .flexWrap = _flexWrap, .alignContent = _alignContent};
const auto unpositionedLayout = ASStackUnpositionedLayout::compute(stackChildren, style, constrainedSize); const auto unpositionedLayout = ASStackUnpositionedLayout::compute(stackChildren, style, constrainedSize, _concurrent);
const auto positionedLayout = ASStackPositionedLayout::compute(unpositionedLayout, style, constrainedSize); const auto positionedLayout = ASStackPositionedLayout::compute(unpositionedLayout, style, constrainedSize);
if (style.direction == ASStackLayoutDirectionVertical) { if (style.direction == ASStackLayoutDirectionVertical) {

View File

@ -58,7 +58,8 @@ struct ASStackUnpositionedLayout {
/** Given a set of children, computes the unpositioned layouts for those children. */ /** Given a set of children, computes the unpositioned layouts for those children. */
static ASStackUnpositionedLayout compute(const std::vector<ASStackLayoutSpecChild> &children, static ASStackUnpositionedLayout compute(const std::vector<ASStackLayoutSpecChild> &children,
const ASStackLayoutSpecStyle &style, const ASStackLayoutSpecStyle &style,
const ASSizeRange &sizeRange); const ASSizeRange &sizeRange,
const BOOL concurrent);
static CGFloat baselineForItem(const ASStackLayoutSpecStyle &style, static CGFloat baselineForItem(const ASStackLayoutSpecStyle &style,
const ASStackLayoutSpecItem &l); const ASStackLayoutSpecItem &l);

View File

@ -16,7 +16,6 @@
#import <AsyncDisplayKit/ASDispatch.h> #import <AsyncDisplayKit/ASDispatch.h>
#import <AsyncDisplayKit/ASLayoutSpecUtilities.h> #import <AsyncDisplayKit/ASLayoutSpecUtilities.h>
#import <AsyncDisplayKit/ASLayoutElementStylePrivate.h> #import <AsyncDisplayKit/ASLayoutElementStylePrivate.h>
#import <AsyncDisplayKit/ASThread.h>
CGFloat const kViolationEpsilon = 0.01; CGFloat const kViolationEpsilon = 0.01;
@ -69,7 +68,7 @@ static ASLayout *crossChildLayout(const ASStackLayoutSpecChild &child,
return layout ? : [ASLayout layoutWithLayoutElement:child.element size:{0, 0}]; return layout ? : [ASLayout layoutWithLayoutElement:child.element size:{0, 0}];
} }
static void dispatchApplyIfNeeded(size_t iterationCount, void(^work)(size_t i)) static void dispatchApplyIfNeeded(size_t iterationCount, BOOL forced, void(^work)(size_t i))
{ {
if (iterationCount == 0) { if (iterationCount == 0) {
return; return;
@ -80,7 +79,8 @@ static void dispatchApplyIfNeeded(size_t iterationCount, void(^work)(size_t i))
return; return;
} }
if (ASDisplayNodeThreadIsMain() == NO) { // TODO Once the locking situation in ASDisplayNode has improved, always dispatch if on main
if (forced == NO) {
for (size_t i = 0; i < iterationCount; i++) { for (size_t i = 0; i < iterationCount; i++) {
work(i); work(i);
} }
@ -196,10 +196,11 @@ CGFloat ASStackUnpositionedLayout::computeCrossViolation(const CGFloat crossDime
*/ */
static void stretchItemsAlongCrossDimension(std::vector<ASStackLayoutSpecItem> &items, static void stretchItemsAlongCrossDimension(std::vector<ASStackLayoutSpecItem> &items,
const ASStackLayoutSpecStyle &style, const ASStackLayoutSpecStyle &style,
const BOOL concurrent,
const CGSize parentSize, const CGSize parentSize,
const CGFloat crossSize) const CGFloat crossSize)
{ {
dispatchApplyIfNeeded(items.size(), ^(size_t i) { dispatchApplyIfNeeded(items.size(), concurrent, ^(size_t i) {
auto &item = items[i]; auto &item = items[i];
const ASStackLayoutAlignItems alignItems = alignment(item.child.style.alignSelf, style.alignItems); const ASStackLayoutAlignItems alignItems = alignment(item.child.style.alignSelf, style.alignItems);
if (alignItems == ASStackLayoutAlignItemsStretch) { if (alignItems == ASStackLayoutAlignItemsStretch) {
@ -222,6 +223,7 @@ static void stretchItemsAlongCrossDimension(std::vector<ASStackLayoutSpecItem> &
*/ */
static void stretchLinesAlongCrossDimension(std::vector<ASStackUnpositionedLine> &lines, static void stretchLinesAlongCrossDimension(std::vector<ASStackUnpositionedLine> &lines,
const ASStackLayoutSpecStyle &style, const ASStackLayoutSpecStyle &style,
const BOOL concurrent,
const ASSizeRange &sizeRange, const ASSizeRange &sizeRange,
const CGSize parentSize) const CGSize parentSize)
{ {
@ -239,7 +241,7 @@ static void stretchLinesAlongCrossDimension(std::vector<ASStackUnpositionedLine>
line.crossSize += extraCrossSizePerLine; line.crossSize += extraCrossSizePerLine;
} }
stretchItemsAlongCrossDimension(line.items, style, parentSize, line.crossSize); stretchItemsAlongCrossDimension(line.items, style, concurrent, parentSize, line.crossSize);
} }
} }
@ -425,10 +427,11 @@ ASDISPLAYNODE_INLINE BOOL isFlexibleInBothDirections(const ASStackLayoutSpecChil
*/ */
static void layoutFlexibleChildrenAtZeroSize(std::vector<ASStackLayoutSpecItem> &items, static void layoutFlexibleChildrenAtZeroSize(std::vector<ASStackLayoutSpecItem> &items,
const ASStackLayoutSpecStyle &style, const ASStackLayoutSpecStyle &style,
const BOOL concurrent,
const ASSizeRange &sizeRange, const ASSizeRange &sizeRange,
const CGSize parentSize) const CGSize parentSize)
{ {
dispatchApplyIfNeeded(items.size(), ^(size_t i) { dispatchApplyIfNeeded(items.size(), concurrent, ^(size_t i) {
auto &item = items[i]; auto &item = items[i];
if (isFlexibleInBothDirections(item.child)) { if (isFlexibleInBothDirections(item.child)) {
item.layout = crossChildLayout(item.child, item.layout = crossChildLayout(item.child,
@ -550,6 +553,7 @@ ASDISPLAYNODE_INLINE BOOL useOptimizedFlexing(const std::vector<ASStackLayoutSpe
*/ */
static void flexLinesAlongStackDimension(std::vector<ASStackUnpositionedLine> &lines, static void flexLinesAlongStackDimension(std::vector<ASStackUnpositionedLine> &lines,
const ASStackLayoutSpecStyle &style, const ASStackLayoutSpecStyle &style,
const BOOL concurrent,
const ASSizeRange &sizeRange, const ASSizeRange &sizeRange,
const CGSize parentSize, const CGSize parentSize,
const BOOL useOptimizedFlexing) const BOOL useOptimizedFlexing)
@ -567,7 +571,7 @@ static void flexLinesAlongStackDimension(std::vector<ASStackUnpositionedLine> &l
if (flexFactorSum == 0) { if (flexFactorSum == 0) {
// If optimized flexing was used then we have to clean up the unsized children and lay them out at zero size. // If optimized flexing was used then we have to clean up the unsized children and lay them out at zero size.
if (useOptimizedFlexing) { if (useOptimizedFlexing) {
layoutFlexibleChildrenAtZeroSize(items, style, sizeRange, parentSize); layoutFlexibleChildrenAtZeroSize(items, style, concurrent, sizeRange, parentSize);
} }
return; return;
} }
@ -591,7 +595,7 @@ static void flexLinesAlongStackDimension(std::vector<ASStackUnpositionedLine> &l
} }
ASDisplayNodeCAssert(firstFlexItem != -1, @"At this point there must be at least 1 flexible item"); ASDisplayNodeCAssert(firstFlexItem != -1, @"At this point there must be at least 1 flexible item");
dispatchApplyIfNeeded(items.size(), ^(size_t i) { dispatchApplyIfNeeded(items.size(), concurrent, ^(size_t i) {
auto &item = items[i]; auto &item = items[i];
const CGFloat currentFlexAdjustment = flexAdjustment(item); const CGFloat currentFlexAdjustment = flexAdjustment(item);
// Children are consider inflexible if they do not need to make a flex adjustment. // Children are consider inflexible if they do not need to make a flex adjustment.
@ -655,6 +659,7 @@ static std::vector<ASStackUnpositionedLine> collectChildrenIntoLines(const std::
*/ */
static void layoutItemsAlongUnconstrainedStackDimension(std::vector<ASStackLayoutSpecItem> &items, static void layoutItemsAlongUnconstrainedStackDimension(std::vector<ASStackLayoutSpecItem> &items,
const ASStackLayoutSpecStyle &style, const ASStackLayoutSpecStyle &style,
const BOOL concurrent,
const ASSizeRange &sizeRange, const ASSizeRange &sizeRange,
const CGSize parentSize, const CGSize parentSize,
const BOOL useOptimizedFlexing) const BOOL useOptimizedFlexing)
@ -662,7 +667,7 @@ static void layoutItemsAlongUnconstrainedStackDimension(std::vector<ASStackLayou
const CGFloat minCrossDimension = crossDimension(style.direction, sizeRange.min); const CGFloat minCrossDimension = crossDimension(style.direction, sizeRange.min);
const CGFloat maxCrossDimension = crossDimension(style.direction, sizeRange.max); const CGFloat maxCrossDimension = crossDimension(style.direction, sizeRange.max);
dispatchApplyIfNeeded(items.size(), ^(size_t i) { dispatchApplyIfNeeded(items.size(), concurrent, ^(size_t i) {
auto &item = items[i]; auto &item = items[i];
if (useOptimizedFlexing && isFlexibleInBothDirections(item.child)) { if (useOptimizedFlexing && isFlexibleInBothDirections(item.child)) {
item.layout = [ASLayout layoutWithLayoutElement:item.child.element size:{0, 0}]; item.layout = [ASLayout layoutWithLayoutElement:item.child.element size:{0, 0}];
@ -680,7 +685,8 @@ static void layoutItemsAlongUnconstrainedStackDimension(std::vector<ASStackLayou
ASStackUnpositionedLayout ASStackUnpositionedLayout::compute(const std::vector<ASStackLayoutSpecChild> &children, ASStackUnpositionedLayout ASStackUnpositionedLayout::compute(const std::vector<ASStackLayoutSpecChild> &children,
const ASStackLayoutSpecStyle &style, const ASStackLayoutSpecStyle &style,
const ASSizeRange &sizeRange) const ASSizeRange &sizeRange,
const BOOL concurrent)
{ {
if (children.empty()) { if (children.empty()) {
return {}; return {};
@ -705,6 +711,7 @@ ASStackUnpositionedLayout ASStackUnpositionedLayout::compute(const std::vector<A
// which determines whether we must grow or shrink the flexible children. // which determines whether we must grow or shrink the flexible children.
layoutItemsAlongUnconstrainedStackDimension(items, layoutItemsAlongUnconstrainedStackDimension(items,
style, style,
concurrent,
sizeRange, sizeRange,
parentSize, parentSize,
optimizedFlexing); optimizedFlexing);
@ -713,14 +720,14 @@ ASStackUnpositionedLayout ASStackUnpositionedLayout::compute(const std::vector<A
std::vector<ASStackUnpositionedLine> lines = collectChildrenIntoLines(items, style, sizeRange); std::vector<ASStackUnpositionedLine> lines = collectChildrenIntoLines(items, style, sizeRange);
// Resolve the flexible lengths (https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths) // Resolve the flexible lengths (https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths)
flexLinesAlongStackDimension(lines, style, sizeRange, parentSize, optimizedFlexing); flexLinesAlongStackDimension(lines, style, concurrent, sizeRange, parentSize, optimizedFlexing);
// Calculate the cross size of each flex line (https://www.w3.org/TR/css-flexbox-1/#algo-cross-line) // Calculate the cross size of each flex line (https://www.w3.org/TR/css-flexbox-1/#algo-cross-line)
computeLinesCrossSizeAndBaseline(lines, style, sizeRange); computeLinesCrossSizeAndBaseline(lines, style, sizeRange);
// Handle 'align-content: stretch' (https://www.w3.org/TR/css-flexbox-1/#algo-line-stretch) // Handle 'align-content: stretch' (https://www.w3.org/TR/css-flexbox-1/#algo-line-stretch)
// Determine the used cross size of each item (https://www.w3.org/TR/css-flexbox-1/#algo-stretch) // Determine the used cross size of each item (https://www.w3.org/TR/css-flexbox-1/#algo-stretch)
stretchLinesAlongCrossDimension(lines, style, sizeRange, parentSize); stretchLinesAlongCrossDimension(lines, style, concurrent, sizeRange, parentSize);
// Compute stack dimension sum of each line and the whole stack // Compute stack dimension sum of each line and the whole stack
CGFloat layoutStackDimensionSum = 0; CGFloat layoutStackDimensionSum = 0;