Merge pull request #2376 from zhongwuzw/fix-race-condition

This commit is contained in:
DreamPiggy 2018-07-11 12:05:10 +08:00 committed by GitHub
commit 76215d7717
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 12 additions and 7 deletions

View File

@ -18,7 +18,7 @@ typedef void(^SDExternalCompletionBlock)(UIImage * _Nullable image, NSError * _N
typedef void(^SDInternalCompletionBlock)(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL);
// A combined operation representing the cache and loader operation. You can it to cancel the load process.
// A combined operation representing the cache and loader operation. You can use it to cancel the load process.
@interface SDWebImageCombinedOperation : NSObject <SDWebImageOperation>
/**

View File

@ -15,7 +15,9 @@
// These value are just used as incrementing counter, keep thread-safe using memory_order_relaxed for performance.
atomic_ulong _skippedCount;
atomic_ulong _finishedCount;
atomic_ulong _totalCount;
atomic_flag _isAllFinished;
unsigned long _totalCount;
}
@property (nonatomic, copy, readwrite) NSArray<NSURL *> *urls;
@ -78,6 +80,7 @@
token->_skippedCount = 0;
token->_finishedCount = 0;
token->_totalCount = token.urls.count;
atomic_flag_clear(&(token->_isAllFinished));
token.operations = [NSPointerArray weakObjectsPointerArray];
token.progressBlock = progressBlock;
token.completionBlock = completionBlock;
@ -103,10 +106,12 @@
// Current operation finished
[sself callProgressBlockForToken:token imageURL:imageURL];
if (atomic_load_explicit(&(token->_finishedCount), memory_order_relaxed) + atomic_load_explicit(&(token->_skippedCount), memory_order_relaxed) >= atomic_load_explicit(&(token->_totalCount), memory_order_relaxed)) {
if (atomic_load_explicit(&(token->_finishedCount), memory_order_relaxed) == token->_totalCount) {
// All finished
[sself callCompletionBlockForToken:token];
[sself removeRunningToken:token];
if (!atomic_flag_test_and_set_explicit(&(token->_isAllFinished), memory_order_relaxed)) {
[sself callCompletionBlockForToken:token];
[sself removeRunningToken:token];
}
}
}];
@synchronized (token) {
@ -134,7 +139,7 @@
NSUInteger tokenFinishedCount = [self tokenFinishedCount];
NSUInteger tokenTotalCount = [self tokenTotalCount];
NSUInteger finishedCount = atomic_load_explicit(&(token->_finishedCount), memory_order_relaxed);
NSUInteger totalCount = atomic_load_explicit(&(token->_totalCount), memory_order_relaxed);
NSUInteger totalCount = token->_totalCount;
dispatch_async(self.delegateQueue, ^{
if (shouldCallDelegate) {
[self.delegate imagePrefetcher:self didPrefetchURL:url finishedCount:tokenFinishedCount totalCount:tokenTotalCount];
@ -169,7 +174,7 @@
NSUInteger tokenTotalCount = 0;
@synchronized (self.runningTokens) {
for (SDWebImagePrefetchToken *token in self.runningTokens) {
tokenTotalCount += atomic_load_explicit(&(token->_totalCount), memory_order_relaxed);
tokenTotalCount += token->_totalCount;
}
}
return tokenTotalCount;