Authored by DreamPiggy
Committed by GitHub

Merge pull request #2340 from hulizhen/optimization/replace-synchronized

Replace @synchronized with dispatch_semaphore_t in SDWebImageManager
... ... @@ -10,6 +10,9 @@
#import "NSImage+WebCache.h"
#import <objc/message.h>
#define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
#define UNLOCK(lock) dispatch_semaphore_signal(lock);
@interface SDWebImageCombinedOperation : NSObject <SDWebImageOperation>
@property (assign, nonatomic, getter = isCancelled) BOOL cancelled;
... ... @@ -24,7 +27,9 @@
@property (strong, nonatomic, readwrite, nonnull) SDImageCache *imageCache;
@property (strong, nonatomic, readwrite, nonnull) SDWebImageDownloader *imageDownloader;
@property (strong, nonatomic, nonnull) NSMutableSet<NSURL *> *failedURLs;
@property (strong, nonatomic, nonnull) dispatch_semaphore_t failedURLsLock; // a lock to keep the access to `failedURLs` thread-safe
@property (strong, nonatomic, nonnull) NSMutableArray<SDWebImageCombinedOperation *> *runningOperations;
@property (strong, nonatomic, nonnull) dispatch_semaphore_t runningOperationsLock; // a lock to keep the access to `runningOperations` thread-safe
@end
... ... @@ -50,7 +55,9 @@
_imageCache = cache;
_imageDownloader = downloader;
_failedURLs = [NSMutableSet new];
_failedURLsLock = dispatch_semaphore_create(1);
_runningOperations = [NSMutableArray new];
_runningOperationsLock = dispatch_semaphore_create(1);
}
return self;
}
... ... @@ -130,9 +137,9 @@
BOOL isFailedUrl = NO;
if (url) {
@synchronized (self.failedURLs) {
isFailedUrl = [self.failedURLs containsObject:url];
}
LOCK(self.failedURLsLock);
isFailedUrl = [self.failedURLs containsObject:url];
UNLOCK(self.failedURLsLock);
}
if (url.absoluteString.length == 0 || (!(options & SDWebImageRetryFailed) && isFailedUrl)) {
... ... @@ -140,9 +147,9 @@
return operation;
}
@synchronized (self.runningOperations) {
[self.runningOperations addObject:operation];
}
LOCK(self.runningOperationsLock);
[self.runningOperations addObject:operation];
UNLOCK(self.runningOperationsLock);
NSString *key = [self cacheKeyForURL:url];
SDImageCacheOptions cacheOptions = 0;
... ... @@ -213,16 +220,16 @@
}
if (shouldBlockFailedURL) {
@synchronized (self.failedURLs) {
[self.failedURLs addObject:url];
}
LOCK(self.failedURLsLock);
[self.failedURLs addObject:url];
UNLOCK(self.failedURLsLock);
}
}
else {
if ((options & SDWebImageRetryFailed)) {
@synchronized (self.failedURLs) {
[self.failedURLs removeObject:url];
}
LOCK(self.failedURLsLock);
[self.failedURLs removeObject:url];
UNLOCK(self.failedURLsLock);
}
BOOL cacheOnDisk = !(options & SDWebImageCacheMemoryOnly);
... ... @@ -292,27 +299,27 @@
}
- (void)cancelAll {
@synchronized (self.runningOperations) {
NSArray<SDWebImageCombinedOperation *> *copiedOperations = [self.runningOperations copy];
[copiedOperations makeObjectsPerformSelector:@selector(cancel)];
[self.runningOperations removeObjectsInArray:copiedOperations];
}
LOCK(self.runningOperationsLock);
NSArray<SDWebImageCombinedOperation *> *copiedOperations = [self.runningOperations copy];
UNLOCK(self.runningOperationsLock);
[copiedOperations makeObjectsPerformSelector:@selector(cancel)]; // This will call `safelyRemoveOperationFromRunning:` and remove from the array
}
- (BOOL)isRunning {
BOOL isRunning = NO;
@synchronized (self.runningOperations) {
isRunning = (self.runningOperations.count > 0);
}
LOCK(self.runningOperationsLock);
isRunning = (self.runningOperations.count > 0);
UNLOCK(self.runningOperationsLock);
return isRunning;
}
- (void)safelyRemoveOperationFromRunning:(nullable SDWebImageCombinedOperation*)operation {
@synchronized (self.runningOperations) {
if (operation) {
[self.runningOperations removeObject:operation];
}
if (!operation) {
return;
}
LOCK(self.runningOperationsLock);
[self.runningOperations removeObject:operation];
UNLOCK(self.runningOperationsLock);
}
- (void)callCompletionBlockForOperation:(nullable SDWebImageCombinedOperation*)operation
... ...