From 4829a8643dd1eb96511853ff41063190f0b28ee9 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Mon, 19 Jun 2017 10:14:39 -0700 Subject: [PATCH] Improve System Trace Implementation #trivial (#368) * Improve the kdebug, system trace integration * Remove superseded subsystem * Address review comments * Please the license header gods * Address harder * Fix node block retaining collection view --- AsyncDisplayKit.xcodeproj/project.pbxproj | 1 + .../SystemTrace.tracetemplate | Bin 0 -> 171474 bytes Source/ASCollectionView.mm | 2 +- Source/ASDisplayNode.mm | 18 ++++- Source/ASRunLoopQueue.mm | 71 ++++++++++++++++- Source/Base/ASAssert.m | 8 +- Source/Base/ASBaseDefines.h | 18 +++++ Source/Base/ASLog.h | 73 ++++++++++++++---- Source/Details/ASDataController.mm | 50 ++---------- Source/Details/ASRangeController.mm | 4 +- Source/Details/ASThread.h | 2 - .../Transactions/_ASAsyncTransaction.mm | 4 - Source/Layout/ASLayoutElement.mm | 23 ++---- Source/Private/ASDisplayNode+AsyncDisplay.mm | 14 ++++ .../Component/ASTextDebugOption.m | 1 - Tests/ASTableViewThrashTests.m | 22 ++++-- 16 files changed, 209 insertions(+), 102 deletions(-) create mode 100644 InstrumentsTemplates/SystemTrace.tracetemplate diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 2cd660f06b..53ab654378 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -2627,6 +2627,7 @@ GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREPROCESSOR_DEFINITIONS = "PROFILE=1"; INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; diff --git a/InstrumentsTemplates/SystemTrace.tracetemplate b/InstrumentsTemplates/SystemTrace.tracetemplate new file mode 100644 index 0000000000000000000000000000000000000000..48cc3e6aef2b107877b7be090f060d1c1ca6a318 GIT binary patch literal 171474 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 #import #import - +#import #import #import #import @@ -78,16 +78,20 @@ static void runLoopSourceCallback(void *info) { return; } // The scope below is entered while already locked. @autorelease is crucial here; see PR 2890. + NSInteger count; @autoreleasepool { #if ASRunLoopQueueLoggingEnabled NSLog(@"ASDeallocQueue Processing: %lu objects destroyed", weakSelf->_queue.size()); #endif // Sometimes we release 10,000 objects at a time. Don't hold the lock while releasing. std::deque currentQueue = weakSelf->_queue; + count = currentQueue.size(); + ASSignpostStartCustom(ASSignpostDeallocQueueDrain, self, count); weakSelf->_queue = std::deque(); weakSelf->_queueLock.unlock(); currentQueue.clear(); } + ASSignpostEndCustom(ASSignpostDeallocQueueDrain, self, count, ASSignpostColorDefault); }); CFRunLoopRef runloop = CFRunLoopGetCurrent(); @@ -196,8 +200,69 @@ static void runLoopSourceCallback(void *info) { @end +#if AS_KDEBUG_ENABLE +/** + * This is real, private CA API. Valid as of iOS 10. + */ +typedef enum { + kCATransactionPhasePreLayout, + kCATransactionPhasePreCommit, + kCATransactionPhasePostCommit, +} CATransactionPhase; + +@interface CATransaction (Private) ++ (void)addCommitHandler:(void(^)(void))block forPhase:(CATransactionPhase)phase; ++ (int)currentState; +@end +#endif + @implementation ASRunLoopQueue +#if AS_KDEBUG_ENABLE ++ (void)load +{ + [self registerCATransactionObservers]; +} + ++ (void)registerCATransactionObservers +{ + static BOOL privateCAMethodsExist; + static dispatch_block_t preLayoutHandler; + static dispatch_block_t preCommitHandler; + static dispatch_block_t postCommitHandler; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + privateCAMethodsExist = [CATransaction respondsToSelector:@selector(addCommitHandler:forPhase:)]; + privateCAMethodsExist &= [CATransaction respondsToSelector:@selector(currentState)]; + if (!privateCAMethodsExist) { + NSLog(@"Private CA methods are gone."); + } + preLayoutHandler = ^{ + ASSignpostStartCustom(ASSignpostCATransactionLayout, 0, [CATransaction currentState]); + }; + preCommitHandler = ^{ + int state = [CATransaction currentState]; + ASSignpostEndCustom(ASSignpostCATransactionLayout, 0, state, ASSignpostColorDefault); + ASSignpostStartCustom(ASSignpostCATransactionCommit, 0, state); + }; + postCommitHandler = ^{ + ASSignpostEndCustom(ASSignpostCATransactionCommit, 0, [CATransaction currentState], ASSignpostColorDefault); + // Can't add new observers inside an observer. rdar://problem/31253952 + dispatch_async(dispatch_get_main_queue(), ^{ + [self registerCATransactionObservers]; + }); + }; + }); + + if (privateCAMethodsExist) { + [CATransaction addCommitHandler:preLayoutHandler forPhase:kCATransactionPhasePreLayout]; + [CATransaction addCommitHandler:preCommitHandler forPhase:kCATransactionPhasePreCommit]; + [CATransaction addCommitHandler:postCommitHandler forPhase:kCATransactionPhasePostCommit]; + } +} + +#endif // AS_KDEBUG_ENABLE + - (instancetype)initWithRunLoop:(CFRunLoopRef)runloop retainObjects:(BOOL)retainsObjects handler:(void (^)(id _Nullable, BOOL))handlerBlock { if (self = [super init]) { @@ -275,7 +340,7 @@ static void runLoopSourceCallback(void *info) { return; } - ASProfilingSignpostStart(0, self); + ASSignpostStart(ASSignpostRunLoopQueueBatch); // Snatch the next batch of items. NSInteger maxCountToProcess = MIN(internalQueueCount, self.batchSize); @@ -329,7 +394,7 @@ static void runLoopSourceCallback(void *info) { CFRunLoopWakeUp(_runLoop); } - ASProfilingSignpostEnd(0, self); + ASSignpostEnd(ASSignpostRunLoopQueueBatch); } - (void)enqueue:(id)object diff --git a/Source/Base/ASAssert.m b/Source/Base/ASAssert.m index b52f2f4b3b..7759ff53f0 100644 --- a/Source/Base/ASAssert.m +++ b/Source/Base/ASAssert.m @@ -13,15 +13,9 @@ #import #import -// pthread_key_create must be called before the key can be used. This function does that. static pthread_key_t ASMainThreadAssertionsDisabledKey() { - static pthread_key_t ASMainThreadAssertionsDisabledKey; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - pthread_key_create(&ASMainThreadAssertionsDisabledKey, NULL); - }); - return ASMainThreadAssertionsDisabledKey; + return ASPthreadStaticKey(NULL); } BOOL ASMainThreadAssertionsAreDisabled() { diff --git a/Source/Base/ASBaseDefines.h b/Source/Base/ASBaseDefines.h index 2fedafdfa2..b269096f48 100755 --- a/Source/Base/ASBaseDefines.h +++ b/Source/Base/ASBaseDefines.h @@ -215,6 +215,24 @@ #define AS_SUBCLASSING_RESTRICTED #endif +#define ASPthreadStaticKey(dtor) ({ \ + static dispatch_once_t onceToken; \ + static pthread_key_t key; \ + dispatch_once(&onceToken, ^{ \ + pthread_key_create(&key, dtor); \ + }); \ + key; \ +}) + +#define ASCreateOnce(expr) ({ \ + static dispatch_once_t onceToken; \ + static __typeof__(expr) staticVar; \ + dispatch_once(&onceToken, ^{ \ + staticVar = expr; \ + }); \ + staticVar; \ +}) + /// Ensure that class is of certain kind #define ASDynamicCast(x, c) ({ \ id __val = x;\ diff --git a/Source/Base/ASLog.h b/Source/Base/ASLog.h index 873702402f..ae734e0ba8 100644 --- a/Source/Base/ASLog.h +++ b/Source/Base/ASLog.h @@ -16,9 +16,45 @@ // #import +#import -#pragma once +/// The signposts we use. Signposts are grouped by color. The SystemTrace.tracetemplate file +/// should be kept up-to-date with these values. +typedef NS_ENUM(uint32_t, ASSignpostName) { + // Collection/Table (Blue) + ASSignpostDataControllerBatch = 300, // Alloc/layout nodes before collection update. + ASSignpostRangeControllerUpdate, // Ranges update pass. + ASSignpostCollectionUpdate, // Entire update process, from -endUpdates to [super perform…] + // Rendering (Green) + ASSignpostLayerDisplay = 325, // Client display callout. + ASSignpostRunLoopQueueBatch, // One batch of ASRunLoopQueue. + + // Layout (Purple) + ASSignpostCalculateLayout = 350, // Start of calculateLayoutThatFits to end. Max 1 per thread. + + // Misc (Orange) + ASSignpostDeallocQueueDrain = 375, // One chunk of dealloc queue work. arg0 is count. + ASSignpostCATransactionLayout, // The CA transaction commit layout phase. + ASSignpostCATransactionCommit // The CA transaction commit post-layout phase. +}; + +typedef NS_ENUM(uintptr_t, ASSignpostColor) { + ASSignpostColorBlue, + ASSignpostColorGreen, + ASSignpostColorPurple, + ASSignpostColorOrange, + ASSignpostColorRed, + ASSignpostColorDefault +}; + +static inline ASSignpostColor ASSignpostGetColor(ASSignpostName name, ASSignpostColor colorPref) { + if (colorPref == ASSignpostColorDefault) { + return (ASSignpostColor)((name / 25) % 4); + } else { + return colorPref; + } +} #define ASMultiplexImageNodeLogDebug(...) #define ASMultiplexImageNodeCLogDebug(...) @@ -26,8 +62,9 @@ #define ASMultiplexImageNodeLogError(...) #define ASMultiplexImageNodeCLogError(...) -// Note: `` only exists in Xcode 8 and later. -#if defined(PROFILE) && __has_include() +#define AS_KDEBUG_ENABLE defined(PROFILE) && __has_include() + +#if AS_KDEBUG_ENABLE #import @@ -45,21 +82,27 @@ #define APPSDBG_CODE(SubClass,code) KDBG_CODE(DBG_APPS, SubClass, code) #endif -#define ASProfilingSignpost(x) \ - AS_AT_LEAST_IOS10 ? kdebug_signpost(x, 0, 0, 0, (uint32_t)(x % 4)) \ - : syscall(SYS_kdebug_trace, APPSDBG_CODE(DBG_MACH_CHUD, x) | DBG_FUNC_NONE, 0, 0, 0, (uint32_t)(x % 4)); +// Currently we'll reserve arg3. +#define ASSignpost(name, identifier, arg2, color) \ + AS_AT_LEAST_IOS10 ? kdebug_signpost(name, (uintptr_t)identifier, (uintptr_t)arg2, 0, ASSignpostGetColor(name, color)) \ + : syscall(SYS_kdebug_trace, APPSDBG_CODE(DBG_MACH_CHUD, name) | DBG_FUNC_NONE, (uintptr_t)identifier, (uintptr_t)arg2, 0, ASSignpostGetColor(name, color)); -#define ASProfilingSignpostStart(x, y) \ - AS_AT_LEAST_IOS10 ? kdebug_signpost_start((uint32_t)x, (uintptr_t)y, 0, 0, (uint32_t)(x % 4)) \ - : syscall(SYS_kdebug_trace, APPSDBG_CODE(DBG_MACH_CHUD, x) | DBG_FUNC_START, (uintptr_t)y, 0, 0, (uint32_t)(x % 4)); +#define ASSignpostStartCustom(name, identifier, arg2) \ + AS_AT_LEAST_IOS10 ? kdebug_signpost_start(name, (uintptr_t)identifier, (uintptr_t)arg2, 0, 0) \ + : syscall(SYS_kdebug_trace, APPSDBG_CODE(DBG_MACH_CHUD, name) | DBG_FUNC_START, (uintptr_t)identifier, (uintptr_t)arg2, 0, 0); +#define ASSignpostStart(name) ASSignpostStartCustom(name, self, 0) + +#define ASSignpostEndCustom(name, identifier, arg2, color) \ + AS_AT_LEAST_IOS10 ? kdebug_signpost_end(name, (uintptr_t)identifier, (uintptr_t)arg2, 0, ASSignpostGetColor(name, color)) \ + : syscall(SYS_kdebug_trace, APPSDBG_CODE(DBG_MACH_CHUD, name) | DBG_FUNC_END, (uintptr_t)identifier, (uintptr_t)arg2, 0, ASSignpostGetColor(name, color)); +#define ASSignpostEnd(name) ASSignpostEndCustom(name, self, 0, ASSignpostColorDefault) -#define ASProfilingSignpostEnd(x, y) \ - AS_AT_LEAST_IOS10 ? kdebug_signpost_end((uint32_t)x, (uintptr_t)y, 0, 0, (uint32_t)(x % 4)) \ - : syscall(SYS_kdebug_trace, APPSDBG_CODE(DBG_MACH_CHUD, x) | DBG_FUNC_END, (uintptr_t)y, 0, 0, (uint32_t)(x % 4)); #else -#define ASProfilingSignpost(x) -#define ASProfilingSignpostStart(x, y) -#define ASProfilingSignpostEnd(x, y) +#define ASSignpost(name, identifier, arg2, color) +#define ASSignpostStartCustom(name, identifier, arg2) +#define ASSignpostStart(name) +#define ASSignpostEndCustom(name, identifier, arg2, color) +#define ASSignpostEnd(name) #endif diff --git a/Source/Details/ASDataController.mm b/Source/Details/ASDataController.mm index d2d5974ea3..a8cccd45ac 100644 --- a/Source/Details/ASDataController.mm +++ b/Source/Details/ASDataController.mm @@ -40,8 +40,6 @@ //#define LOG(...) NSLog(__VA_ARGS__) #define LOG(...) -#define AS_MEASURE_AVOIDED_DATACONTROLLER_WORK 0 - #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)) @@ -54,13 +52,6 @@ NSString * const ASCollectionInvalidUpdateException = @"ASCollectionInvalidUpdat typedef void (^ASDataControllerCompletionBlock)(NSArray *elements, NSArray *nodes); -#if AS_MEASURE_AVOIDED_DATACONTROLLER_WORK -@interface ASDataController (AvoidedWorkMeasuring) -+ (void)_didLayoutNode; -+ (void)_expectToInsertNodes:(NSUInteger)count; -@end -#endif - @interface ASDataController () { id _layoutDelegate; @@ -159,17 +150,14 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray * - (void)batchAllocateNodesFromElements:(NSArray *)elements andLayout:(BOOL)shouldLayout batchSize:(NSInteger)batchSize batchCompletion:(ASDataControllerCompletionBlock)batchCompletionHandler { ASSERT_ON_EDITING_QUEUE; -#if AS_MEASURE_AVOIDED_DATACONTROLLER_WORK - [ASDataController _expectToInsertNodes:elements.count]; -#endif - + if (elements.count == 0 || _dataSource == nil) { batchCompletionHandler(@[], @[]); return; } - ASProfilingSignpostStart(2, _dataSource); - + ASSignpostStart(ASSignpostDataControllerBatch); + if (batchSize == 0) { batchSize = [[ASDataController class] parallelProcessorCount] * kASDataControllerSizingCountPerProcessor; } @@ -182,8 +170,8 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray * NSArray *nodes = [self _allocateNodesFromElements:batchedElements andLayout:shouldLayout]; batchCompletionHandler(batchedElements, nodes); } - - ASProfilingSignpostEnd(2, _dataSource); + + ASSignpostEndCustom(ASSignpostDataControllerBatch, self, 0, (_dataSource != nil ? ASSignpostColorDefault : ASSignpostColorRed)); } /** @@ -228,10 +216,6 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray * if (ASSizeRangeHasSignificantArea(sizeRange)) { [self _layoutNode:node withConstrainedSize:sizeRange]; } - -#if AS_MEASURE_AVOIDED_DATACONTROLLER_WORK - [ASDataController _didLayoutNode]; -#endif } allocatedNodeBuffer[i] = node; @@ -836,27 +820,3 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray * } @end - -#if AS_MEASURE_AVOIDED_DATACONTROLLER_WORK - -static volatile int64_t _totalExpectedItems = 0; -static volatile int64_t _totalMeasuredNodes = 0; - -@implementation ASDataController (WorkMeasuring) - -+ (void)_didLayoutNode -{ - int64_t measured = OSAtomicIncrement64(&_totalMeasuredNodes); - int64_t expected = _totalExpectedItems; - if (measured % 20 == 0 || measured == expected) { - NSLog(@"Data controller avoided work (underestimated): %lld / %lld", measured, expected); - } -} - -+ (void)_expectToInsertNodes:(NSUInteger)count -{ - OSAtomicAdd64((int64_t)count, &_totalExpectedItems); -} - -@end -#endif diff --git a/Source/Details/ASRangeController.mm b/Source/Details/ASRangeController.mm index 700b38fdb3..cf0acaab6e 100644 --- a/Source/Details/ASRangeController.mm +++ b/Source/Details/ASRangeController.mm @@ -223,7 +223,7 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive; [self _setVisibleNodes:newVisibleNodes]; return; // don't do anything for this update, but leave _rangeIsValid == NO to make sure we update it later } - ASProfilingSignpostStart(1, self); + ASSignpostStart(ASSignpostRangeControllerUpdate); // Get the scroll direction. Default to using the previous one, if they're not scrolling. ASScrollDirection scrollDirection = [_dataSource scrollDirectionForRangeController:self]; @@ -412,7 +412,7 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive; NSLog(@"Range update complete; modifiedIndexPaths: %@", [self descriptionWithIndexPaths:modifiedIndexPaths]); #endif - ASProfilingSignpostEnd(1, self); + ASSignpostEnd(ASSignpostRangeControllerUpdate); } #pragma mark - Notification observers diff --git a/Source/Details/ASThread.h b/Source/Details/ASThread.h index 2c30cf501b..ca049d72a4 100644 --- a/Source/Details/ASThread.h +++ b/Source/Details/ASThread.h @@ -22,8 +22,6 @@ #import #import -#import - #import #import diff --git a/Source/Details/Transactions/_ASAsyncTransaction.mm b/Source/Details/Transactions/_ASAsyncTransaction.mm index 0294a1013f..a7c25b9487 100644 --- a/Source/Details/Transactions/_ASAsyncTransaction.mm +++ b/Source/Details/Transactions/_ASAsyncTransaction.mm @@ -21,12 +21,10 @@ #import #import #import -#import #import #import #import #import -#import #define ASAsyncTransactionAssertMainThread() NSAssert(0 != pthread_main_np(), @"This method must be called on the main thread"); @@ -254,9 +252,7 @@ void ASAsyncTransactionQueue::GroupImpl::schedule(NSInteger priority, dispatch_q Operation operation = entry.popNextOperation(respectPriority); lock.unlock(); if (operation._block) { - ASProfilingSignpostStart(3, operation._block); operation._block(); - ASProfilingSignpostEnd(3, operation._block); } operation._group->leave(); operation._block = nil; // the block must be freed while mutex is unlocked diff --git a/Source/Layout/ASLayoutElement.mm b/Source/Layout/ASLayoutElement.mm index c8ad2d379f..8d647c09aa 100644 --- a/Source/Layout/ASLayoutElement.mm +++ b/Source/Layout/ASLayoutElement.mm @@ -50,8 +50,6 @@ CGSize const ASLayoutElementParentSizeUndefined = {ASLayoutElementParentDimensio int32_t const ASLayoutElementContextInvalidTransitionID = 0; int32_t const ASLayoutElementContextDefaultTransitionID = ASLayoutElementContextInvalidTransitionID + 1; -pthread_key_t ASLayoutElementContextKey; - static void ASLayoutElementDestructor(void *p) { if (p != NULL) { ASDisplayNodeCFailAssert(@"Thread exited without clearing layout element context!"); @@ -59,36 +57,31 @@ static void ASLayoutElementDestructor(void *p) { } }; -// pthread_key_create must be called before the key can be used. This function does that. -void ASLayoutElementContextEnsureKey() +pthread_key_t ASLayoutElementContextKey() { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - pthread_key_create(&ASLayoutElementContextKey, ASLayoutElementDestructor); - }); + return ASPthreadStaticKey(ASLayoutElementDestructor); } void ASLayoutElementPushContext(ASLayoutElementContext *context) { - ASLayoutElementContextEnsureKey(); // NOTE: It would be easy to support nested contexts – just use an NSMutableArray here. ASDisplayNodeCAssertNil(ASLayoutElementGetCurrentContext(), @"Nested ASLayoutElementContexts aren't supported."); - pthread_setspecific(ASLayoutElementContextKey, CFBridgingRetain(context)); + pthread_setspecific(ASLayoutElementContextKey(), CFBridgingRetain(context)); } ASLayoutElementContext *ASLayoutElementGetCurrentContext() { - ASLayoutElementContextEnsureKey(); // Don't retain here. Caller will retain if it wants to! - return (__bridge __unsafe_unretained ASLayoutElementContext *)pthread_getspecific(ASLayoutElementContextKey); + return (__bridge __unsafe_unretained ASLayoutElementContext *)pthread_getspecific(ASLayoutElementContextKey()); } void ASLayoutElementPopContext() { - ASLayoutElementContextEnsureKey(); + ASLayoutElementContextKey(); ASDisplayNodeCAssertNotNil(ASLayoutElementGetCurrentContext(), @"Attempt to pop context when there wasn't a context!"); - CFBridgingRelease(pthread_getspecific(ASLayoutElementContextKey)); - pthread_setspecific(ASLayoutElementContextKey, NULL); + auto key = ASLayoutElementContextKey(); + CFBridgingRelease(pthread_getspecific(key)); + pthread_setspecific(key, NULL); } #pragma mark - ASLayoutElementStyle diff --git a/Source/Private/ASDisplayNode+AsyncDisplay.mm b/Source/Private/ASDisplayNode+AsyncDisplay.mm index 39d8f59b6b..7c9c39ef03 100644 --- a/Source/Private/ASDisplayNode+AsyncDisplay.mm +++ b/Source/Private/ASDisplayNode+AsyncDisplay.mm @@ -272,6 +272,20 @@ }; } + /** + If we're profiling, wrap the display block with signpost start and end. + Color the interval red if cancelled, green otherwise. + */ +#if AS_KDEBUG_ENABLE + __unsafe_unretained id ptrSelf = self; + displayBlock = ^{ + ASSignpostStartCustom(ASSignpostLayerDisplay, ptrSelf, 0); + id result = displayBlock(); + ASSignpostEndCustom(ASSignpostLayerDisplay, ptrSelf, 0, isCancelledBlock() ? ASSignpostColorRed : ASSignpostColorGreen); + return result; + }; +#endif + return displayBlock; } diff --git a/Source/Private/TextExperiment/Component/ASTextDebugOption.m b/Source/Private/TextExperiment/Component/ASTextDebugOption.m index fe36f250ed..e823d328b1 100755 --- a/Source/Private/TextExperiment/Component/ASTextDebugOption.m +++ b/Source/Private/TextExperiment/Component/ASTextDebugOption.m @@ -10,7 +10,6 @@ // #import "ASTextDebugOption.h" -#import #import static pthread_mutex_t _sharedDebugLock; diff --git a/Tests/ASTableViewThrashTests.m b/Tests/ASTableViewThrashTests.m index 34326629ed..e547fe39cb 100644 --- a/Tests/ASTableViewThrashTests.m +++ b/Tests/ASTableViewThrashTests.m @@ -2,14 +2,24 @@ // ASTableViewThrashTests.m // Texture // -// Created by Adlai Holler on 6/21/16. -// Copyright © 2016 Facebook. All rights reserved. +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the /ASDK-Licenses directory of this source tree. An additional +// grant of patent rights can be found in the PATENTS file in the same directory. +// +// Modifications to this file made after 4/13/2017 are: Copyright (c) 2017-present, +// Pinterest, Inc. Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 // #import #import #import #import +#import // Set to 1 to use UITableView and see if the issue still exists. @@ -40,7 +50,7 @@ static NSString *ASThrashArrayDescription(NSArray *array) { return str; } -static volatile int32_t ASThrashTestItemNextID = 1; +static atomic_uint ASThrashTestItemNextID; @interface ASThrashTestItem: NSObject @property (nonatomic, readonly) NSInteger itemID; @@ -56,7 +66,7 @@ static volatile int32_t ASThrashTestItemNextID = 1; - (instancetype)init { self = [super init]; if (self != nil) { - _itemID = OSAtomicIncrement32(&ASThrashTestItemNextID); + _itemID = atomic_fetch_add(&ASThrashTestItemNextID, 1); } return self; } @@ -99,7 +109,7 @@ static volatile int32_t ASThrashTestItemNextID = 1; - (CGFloat)headerHeight; @end -static volatile int32_t ASThrashTestSectionNextID = 1; +static atomic_uint ASThrashTestSectionNextID = 1; @implementation ASThrashTestSection /// Create an array of sections with the given count @@ -114,7 +124,7 @@ static volatile int32_t ASThrashTestSectionNextID = 1; - (instancetype)initWithCount:(NSInteger)count { self = [super init]; if (self != nil) { - _sectionID = OSAtomicIncrement32(&ASThrashTestSectionNextID); + _sectionID = atomic_fetch_add(&ASThrashTestSectionNextID, 1); _items = [ASThrashTestItem itemsWithCount:count]; } return self;