diff --git a/AsyncDisplayKit/Details/Transactions/_ASAsyncTransaction.mm b/AsyncDisplayKit/Details/Transactions/_ASAsyncTransaction.mm index d9c57c6e..ccb9f00a 100644 --- a/AsyncDisplayKit/Details/Transactions/_ASAsyncTransaction.mm +++ b/AsyncDisplayKit/Details/Transactions/_ASAsyncTransaction.mm @@ -10,10 +10,12 @@ #import "_ASAsyncTransaction.h" #import "_ASAsyncTransactionGroup.h" -#import "ASAssert.h" -#import "ASThread.h" + #import #import +#import + +#define ASAsyncTransactionAssertMainThread() NSAssert(0 != pthread_main_np(), @"This method must be called on the main thread"); NSInteger const ASDefaultTransactionPriority = 0; @@ -35,7 +37,7 @@ NSInteger const ASDefaultTransactionPriority = 0; - (void)dealloc { - ASDisplayNodeAssertNil(_operationCompletionBlock, @"Should have been called and released before -dealloc"); + NSAssert(_operationCompletionBlock == nil, @"Should have been called and released before -dealloc"); } - (void)callAndReleaseCompletionBlock:(BOOL)canceled; @@ -115,7 +117,7 @@ private: int _pendingOperations; std::list _notifyList; - ASDN::Condition _condition; + std::condition_variable _condition; BOOL _releaseCalled; ASAsyncTransactionQueue &_queue; }; @@ -142,7 +144,7 @@ private: }; std::map _entries; - ASDN::Mutex _mutex; + std::mutex _mutex; }; ASAsyncTransactionQueue::Group* ASAsyncTransactionQueue::createGroup() @@ -153,7 +155,7 @@ ASAsyncTransactionQueue::Group* ASAsyncTransactionQueue::createGroup() void ASAsyncTransactionQueue::GroupImpl::release() { - ASDN::MutexLocker locker(_queue._mutex); + std::lock_guard l(_queue._mutex); if (_pendingOperations == 0) { delete this; @@ -202,7 +204,7 @@ void ASAsyncTransactionQueue::DispatchEntry::pushOperation(ASAsyncTransactionQue void ASAsyncTransactionQueue::GroupImpl::schedule(NSInteger priority, dispatch_queue_t queue, dispatch_block_t block) { ASAsyncTransactionQueue &q = _queue; - ASDN::MutexLocker locker(q._mutex); + std::lock_guard l(q._mutex); DispatchEntry &entry = q._entries[queue]; @@ -231,19 +233,19 @@ void ASAsyncTransactionQueue::GroupImpl::schedule(NSInteger priority, dispatch_q ++entry._threadCount; dispatch_async(queue, ^{ - ASDN::MutexLocker lock(q._mutex); + std::unique_lock lock(q._mutex); // go until there are no more pending operations while (!entry._operationQueue.empty()) { Operation operation = entry.popNextOperation(respectPriority); - { - ASDN::MutexUnlocker unlock(q._mutex); - if (operation._block) { - operation._block(); - } - operation._group->leave(); - operation._block = nil; // the block must be freed while mutex is unlocked + + lock.unlock(); + if (operation._block) { + operation._block(); } + operation._group->leave(); + operation._block = nil; // the block must be freed while mutex is unlocked + lock.lock(); } --entry._threadCount; @@ -257,8 +259,8 @@ void ASAsyncTransactionQueue::GroupImpl::schedule(NSInteger priority, dispatch_q void ASAsyncTransactionQueue::GroupImpl::notify(dispatch_queue_t queue, dispatch_block_t block) { - ASDN::MutexLocker locker(_queue._mutex); - + std::lock_guard l(_queue._mutex); + if (_pendingOperations == 0) { dispatch_async(queue, block); } else { @@ -271,13 +273,13 @@ void ASAsyncTransactionQueue::GroupImpl::notify(dispatch_queue_t queue, dispatch void ASAsyncTransactionQueue::GroupImpl::enter() { - ASDN::MutexLocker locker(_queue._mutex); + std::lock_guard l(_queue._mutex); ++_pendingOperations; } void ASAsyncTransactionQueue::GroupImpl::leave() { - ASDN::MutexLocker locker(_queue._mutex); + std::lock_guard l(_queue._mutex); --_pendingOperations; if (_pendingOperations == 0) { @@ -288,7 +290,7 @@ void ASAsyncTransactionQueue::GroupImpl::leave() dispatch_async(notify._queue, notify._block); } - _condition.signal(); + _condition.notify_one(); // there was attempt to release the group before, but we still // had operations scheduled so now is good time @@ -300,9 +302,9 @@ void ASAsyncTransactionQueue::GroupImpl::leave() void ASAsyncTransactionQueue::GroupImpl::wait() { - ASDN::MutexLocker locker(_queue._mutex); + std::unique_lock lock(_queue._mutex); while (_pendingOperations > 0) { - _condition.wait(_queue._mutex); + _condition.wait(lock); } } @@ -339,7 +341,7 @@ ASAsyncTransactionQueue & ASAsyncTransactionQueue::instance() - (void)dealloc { // Uncommitted transactions break our guarantees about releasing completion blocks on callbackQueue. - ASDisplayNodeAssert(__atomic_load_n(&_state, __ATOMIC_SEQ_CST) != ASAsyncTransactionStateOpen, @"Uncommitted ASAsyncTransactions are not allowed"); + NSAssert(__atomic_load_n(&_state, __ATOMIC_SEQ_CST) != ASAsyncTransactionStateOpen, @"Uncommitted ASAsyncTransactions are not allowed"); if (_group) { _group->release(); } @@ -363,8 +365,8 @@ ASAsyncTransactionQueue & ASAsyncTransactionQueue::instance() queue:(dispatch_queue_t)queue completion:(asyncdisplaykit_async_transaction_operation_completion_block_t)completion { - ASDisplayNodeAssertMainThread(); - ASDisplayNodeAssert(__atomic_load_n(&_state, __ATOMIC_SEQ_CST) == ASAsyncTransactionStateOpen, @"You can only add operations to open transactions"); + ASAsyncTransactionAssertMainThread(); + NSAssert(__atomic_load_n(&_state, __ATOMIC_SEQ_CST) == ASAsyncTransactionStateOpen, @"You can only add operations to open transactions"); [self _ensureTransactionData]; @@ -398,8 +400,8 @@ ASAsyncTransactionQueue & ASAsyncTransactionQueue::instance() queue:(dispatch_queue_t)queue completion:(asyncdisplaykit_async_transaction_operation_completion_block_t)completion { - ASDisplayNodeAssertMainThread(); - ASDisplayNodeAssert(__atomic_load_n(&_state, __ATOMIC_SEQ_CST) == ASAsyncTransactionStateOpen, @"You can only add operations to open transactions"); + ASAsyncTransactionAssertMainThread(); + NSAssert(__atomic_load_n(&_state, __ATOMIC_SEQ_CST) == ASAsyncTransactionStateOpen, @"You can only add operations to open transactions"); [self _ensureTransactionData]; @@ -425,15 +427,15 @@ ASAsyncTransactionQueue & ASAsyncTransactionQueue::instance() - (void)cancel { - ASDisplayNodeAssertMainThread(); - ASDisplayNodeAssert(__atomic_load_n(&_state, __ATOMIC_SEQ_CST) != ASAsyncTransactionStateOpen, @"You can only cancel a committed or already-canceled transaction"); + ASAsyncTransactionAssertMainThread(); + NSAssert(__atomic_load_n(&_state, __ATOMIC_SEQ_CST) != ASAsyncTransactionStateOpen, @"You can only cancel a committed or already-canceled transaction"); __atomic_store_n(&_state, ASAsyncTransactionStateCanceled, __ATOMIC_SEQ_CST); } - (void)commit { - ASDisplayNodeAssertMainThread(); - ASDisplayNodeAssert(__atomic_load_n(&_state, __ATOMIC_SEQ_CST) == ASAsyncTransactionStateOpen, @"You cannot double-commit a transaction"); + ASAsyncTransactionAssertMainThread(); + NSAssert(__atomic_load_n(&_state, __ATOMIC_SEQ_CST) == ASAsyncTransactionStateOpen, @"You cannot double-commit a transaction"); __atomic_store_n(&_state, ASAsyncTransactionStateCommitted, __ATOMIC_SEQ_CST); if ([_operations count] == 0) { @@ -442,12 +444,12 @@ ASAsyncTransactionQueue & ASAsyncTransactionQueue::instance() _completionBlock(self, NO); } } else { - ASDisplayNodeAssert(_group != NULL, @"If there are operations, dispatch group should have been created"); + 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. - ASDisplayNodeAssertMainThread(); + ASAsyncTransactionAssertMainThread(); [self completeTransaction]; }); } @@ -474,10 +476,10 @@ ASAsyncTransactionQueue & ASAsyncTransactionQueue::instance() - (void)waitUntilComplete { - ASDisplayNodeAssertMainThread(); + ASAsyncTransactionAssertMainThread(); if (__atomic_load_n(&_state, __ATOMIC_SEQ_CST) != ASAsyncTransactionStateComplete) { if (_group) { - ASDisplayNodeAssertTrue(_callbackQueue == dispatch_get_main_queue()); + NSAssert(_callbackQueue == dispatch_get_main_queue(), nil); _group->wait(); // At this point, the asynchronous operation may have completed, but the runloop @@ -487,7 +489,7 @@ ASAsyncTransactionQueue & ASAsyncTransactionQueue::instance() // to continue, e.g. in the implementation of -[ASDisplayNode recursivelyEnsureDisplay]. if (__atomic_load_n(&_state, __ATOMIC_SEQ_CST) == ASAsyncTransactionStateOpen) { [_ASAsyncTransactionGroup commit]; - ASDisplayNodeAssert(__atomic_load_n(&_state, __ATOMIC_SEQ_CST) != ASAsyncTransactionStateOpen, @"Transaction should not be open after committing group"); + NSAssert(__atomic_load_n(&_state, __ATOMIC_SEQ_CST) != ASAsyncTransactionStateOpen, @"Transaction should not be open after committing group"); } // If we needed to commit the group above, -completeTransaction may have already been run. // It is designed to accommodate this by checking _state to ensure it is not complete.