Remove dependencies for ASAssert and ASThread in the async transaction system (#2333)

This commit is contained in:
Michael Schneider
2016-10-04 16:49:14 -07:00
committed by Adlai Holler
parent f369be43dd
commit 2de129008f

View File

@@ -10,10 +10,12 @@
#import "_ASAsyncTransaction.h"
#import "_ASAsyncTransactionGroup.h"
#import "ASAssert.h"
#import "ASThread.h"
#import <list>
#import <map>
#import <mutex>
#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<GroupNotify> _notifyList;
ASDN::Condition _condition;
std::condition_variable _condition;
BOOL _releaseCalled;
ASAsyncTransactionQueue &_queue;
};
@@ -142,7 +144,7 @@ private:
};
std::map<dispatch_queue_t, DispatchEntry> _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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> l(_queue._mutex);
++_pendingOperations;
}
void ASAsyncTransactionQueue::GroupImpl::leave()
{
ASDN::MutexLocker locker(_queue._mutex);
std::lock_guard<std::mutex> 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<std::mutex> 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.