...
|
...
|
@@ -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
|
...
|
...
|
|