Skip to content

Commit

Permalink
Cleanup ASAsyncTransaction a little bit (TextureGroup#316)
Browse files Browse the repository at this point in the history
  • Loading branch information
Adlai-Holler authored and bernieperez committed Apr 25, 2018
1 parent 4a54231 commit a50fd30
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 67 deletions.
14 changes: 3 additions & 11 deletions Source/Details/Transactions/_ASAsyncTransaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ NS_ASSUME_NONNULL_BEGIN

typedef void(^asyncdisplaykit_async_transaction_completion_block_t)(_ASAsyncTransaction *completedTransaction, BOOL canceled);
typedef id<NSObject> _Nullable(^asyncdisplaykit_async_transaction_operation_block_t)(void);
typedef void(^asyncdisplaykit_async_transaction_operation_completion_block_t)(id<NSObject> _Nullable value, BOOL canceled);
typedef void(^asyncdisplaykit_async_transaction_complete_async_operation_block_t)(id<NSObject> _Nullable value);
typedef void(^asyncdisplaykit_async_transaction_operation_completion_block_t)(id _Nullable value, BOOL canceled);
typedef void(^asyncdisplaykit_async_transaction_complete_async_operation_block_t)(id _Nullable value);
typedef void(^asyncdisplaykit_async_transaction_async_operation_block_t)(asyncdisplaykit_async_transaction_complete_async_operation_block_t completeOperationBlock);

/**
Expand Down Expand Up @@ -62,12 +62,9 @@ extern NSInteger const ASDefaultTransactionPriority;
/**
@summary Initialize a transaction that can start collecting async operations.
@see initWithCallbackQueue:commitBlock:completionBlock:executeConcurrently:
@param callbackQueue The dispatch queue that the completion blocks will be called on. Default is the main queue.
@param completionBlock A block that is called when the transaction is completed.
*/
- (instancetype)initWithCallbackQueue:(nullable dispatch_queue_t)callbackQueue
completionBlock:(nullable asyncdisplaykit_async_transaction_completion_block_t)completionBlock;
- (instancetype)initWithCompletionBlock:(nullable asyncdisplaykit_async_transaction_completion_block_t)completionBlock;

/**
@summary Block the main thread until the transaction is complete, including callbacks.
Expand All @@ -76,11 +73,6 @@ extern NSInteger const ASDefaultTransactionPriority;
*/
- (void)waitUntilComplete;

/**
The dispatch queue that the completion blocks will be called on.
*/
@property (nonatomic, readonly, strong) dispatch_queue_t callbackQueue;

/**
A block that is called when the transaction is completed.
*/
Expand Down
49 changes: 17 additions & 32 deletions Source/Details/Transactions/_ASAsyncTransaction.mm
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
@interface ASAsyncTransactionOperation : NSObject
- (instancetype)initWithOperationCompletionBlock:(asyncdisplaykit_async_transaction_operation_completion_block_t)operationCompletionBlock;
@property (nonatomic, copy) asyncdisplaykit_async_transaction_operation_completion_block_t operationCompletionBlock;
@property (nonatomic, strong) id<NSObject> value; // set on bg queue by the operation block
@property (atomic, strong) id value; // set on bg queue by the operation block
@end

@implementation ASAsyncTransactionOperation
Expand All @@ -55,16 +55,17 @@ - (void)dealloc

- (void)callAndReleaseCompletionBlock:(BOOL)canceled;
{
ASDisplayNodeAssertMainThread();
if (_operationCompletionBlock) {
_operationCompletionBlock(self.value, canceled);
// Guarantee that _operationCompletionBlock is released on _callbackQueue:
self.operationCompletionBlock = nil;
// Guarantee that _operationCompletionBlock is released on main thread
_operationCompletionBlock = nil;
}
}

- (NSString *)description
{
return [NSString stringWithFormat:@"<ASAsyncTransactionOperation: %p - value = %@", self, self.value];
return [NSString stringWithFormat:@"<ASAsyncTransactionOperation: %p - value = %@>", self, self.value];
}

@end
Expand Down Expand Up @@ -328,27 +329,25 @@ - (NSString *)description
return *instance;
}

@interface _ASAsyncTransaction ()
@property (atomic) ASAsyncTransactionState state;
@end


@implementation _ASAsyncTransaction
{
ASAsyncTransactionQueue::Group *_group;
NSMutableArray<ASAsyncTransactionOperation *> *_operations;
_Atomic(ASAsyncTransactionState) _state;
}

#pragma mark -
#pragma mark Lifecycle

- (instancetype)initWithCallbackQueue:(dispatch_queue_t)callbackQueue
completionBlock:(void(^)(_ASAsyncTransaction *, BOOL))completionBlock
- (instancetype)initWithCompletionBlock:(void(^)(_ASAsyncTransaction *, BOOL))completionBlock
{
if ((self = [self init])) {
if (callbackQueue == NULL) {
callbackQueue = dispatch_get_main_queue();
}
_callbackQueue = callbackQueue;
_completionBlock = completionBlock;

_state = ATOMIC_VAR_INIT(ASAsyncTransactionStateOpen);
self.state = ASAsyncTransactionStateOpen;
}
return self;
}
Expand All @@ -362,18 +361,6 @@ - (void)dealloc
}
}

#pragma mark - Properties

- (ASAsyncTransactionState)state
{
return atomic_load(&_state);
}

- (void)setState:(ASAsyncTransactionState)state
{
atomic_store(&_state, state);
}

#pragma mark - Transaction Management

- (void)addAsyncOperationWithBlock:(asyncdisplaykit_async_transaction_async_operation_block_t)block
Expand Down Expand Up @@ -402,7 +389,7 @@ - (void)addAsyncOperationWithBlock:(asyncdisplaykit_async_transaction_async_oper
@autoreleasepool {
if (self.state != ASAsyncTransactionStateCanceled) {
_group->enter();
block(^(id<NSObject> value){
block(^(id value){
operation.value = value;
_group->leave();
});
Expand Down Expand Up @@ -445,7 +432,8 @@ - (void)addOperationWithBlock:(asyncdisplaykit_async_transaction_operation_block
- (void)addCompletionBlock:(asyncdisplaykit_async_transaction_completion_block_t)completion
{
__weak __typeof__(self) weakSelf = self;
[self addOperationWithBlock:^(){return (id<NSObject>)nil;} queue:_callbackQueue completion:^(id<NSObject> value, BOOL canceled) {
dispatch_queue_t bsQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
[self addOperationWithBlock:^(){return (id)nil;} queue:bsQueue completion:^(id value, BOOL canceled) {
__typeof__(self) strongSelf = weakSelf;
completion(strongSelf, canceled);
}];
Expand All @@ -472,17 +460,15 @@ - (void)commit
} else {
NSAssert(_group != NULL, @"If there are operations, dispatch group should have been created");

_group->notify(_callbackQueue, ^{
// _callbackQueue is the main queue in current practice (also asserted in -waitUntilComplete).
// This code should be reviewed before taking on significantly different use cases.
ASAsyncTransactionAssertMainThread();
_group->notify(dispatch_get_main_queue(), ^{
[self completeTransaction];
});
}
}

- (void)completeTransaction
{
ASAsyncTransactionAssertMainThread();
ASAsyncTransactionState state = self.state;
if (state != ASAsyncTransactionStateComplete) {
BOOL isCanceled = (state == ASAsyncTransactionStateCanceled);
Expand All @@ -506,7 +492,6 @@ - (void)waitUntilComplete
ASAsyncTransactionAssertMainThread();
if (self.state != ASAsyncTransactionStateComplete) {
if (_group) {
NSAssert(_callbackQueue == dispatch_get_main_queue(), nil);
_group->wait();

// At this point, the asynchronous operation may have completed, but the runloop
Expand Down
4 changes: 2 additions & 2 deletions Source/Details/Transactions/_ASAsyncTransactionContainer.m
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,11 @@ - (_ASAsyncTransaction *)asyncdisplaykit_asyncTransaction
if (transaction == nil) {
NSHashTable *transactions = self.asyncdisplaykit_asyncLayerTransactions;
if (transactions == nil) {
transactions = [NSHashTable hashTableWithOptions:NSPointerFunctionsObjectPointerPersonality];
transactions = [NSHashTable hashTableWithOptions:NSHashTableObjectPointerPersonality];
self.asyncdisplaykit_asyncLayerTransactions = transactions;
}
__weak CALayer *weakSelf = self;
transaction = [[_ASAsyncTransaction alloc] initWithCallbackQueue:dispatch_get_main_queue() completionBlock:^(_ASAsyncTransaction *completedTransaction, BOOL cancelled) {
transaction = [[_ASAsyncTransaction alloc] initWithCompletionBlock:^(_ASAsyncTransaction *completedTransaction, BOOL cancelled) {
__strong CALayer *self = weakSelf;
if (self == nil) {
return;
Expand Down
30 changes: 8 additions & 22 deletions Source/Details/Transactions/_ASAsyncTransactionGroup.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
#import <AsyncDisplayKit/_ASAsyncTransactionContainer.h>
#import <AsyncDisplayKit/_ASAsyncTransactionContainer+Private.h>

static void _transactionGroupRunLoopObserverCallback(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info);

@interface _ASAsyncTransactionGroup ()
+ (void)registerTransactionGroupAsMainRunloopObserver:(_ASAsyncTransactionGroup *)transactionGroup;
- (void)commit;
Expand Down Expand Up @@ -54,20 +52,15 @@ + (void)registerTransactionGroupAsMainRunloopObserver:(_ASAsyncTransactionGroup
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
CFOptionFlags activities = (kCFRunLoopBeforeWaiting | // before the run loop starts sleeping
kCFRunLoopExit); // before exiting a runloop run
CFRunLoopObserverContext context = {
0, // version
(__bridge void *)transactionGroup, // info
&CFRetain, // retain
&CFRelease, // release
NULL // copyDescription
};

observer = CFRunLoopObserverCreate(NULL, // allocator
activities, // activities
YES, // repeats
INT_MAX, // order after CA transaction commits
&_transactionGroupRunLoopObserverCallback, // callback
&context); // context
observer = CFRunLoopObserverCreateWithHandler(NULL, // allocator
activities, // activities
YES, // repeats
INT_MAX, // order after CA transaction commits
^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
ASDisplayNodeCAssertMainThread();
[transactionGroup commit];
});
CFRunLoopAddObserver(runLoop, observer, kCFRunLoopCommonModes);
CFRelease(observer);
}
Expand Down Expand Up @@ -111,10 +104,3 @@ + (void)commit
}

@end

static void _transactionGroupRunLoopObserverCallback(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)
{
ASDisplayNodeCAssertMainThread();
_ASAsyncTransactionGroup *group = (__bridge _ASAsyncTransactionGroup *)info;
[group commit];
}

0 comments on commit a50fd30

Please sign in to comment.