Merge pull request #2645 from zhongwuzw/fix_prefetch_hung_up

Fix prefetch hung up
This commit is contained in:
Kinarobin 2019-03-21 10:42:23 +08:00 committed by GitHub
commit 07204d5a60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 12 deletions

View File

@ -10,14 +10,17 @@
@interface SDAsyncBlockOperation () @interface SDAsyncBlockOperation ()
@property (nonatomic, assign) BOOL isExecuting; @property (assign, nonatomic, getter = isExecuting) BOOL executing;
@property (nonatomic, assign) BOOL isFinished; @property (assign, nonatomic, getter = isFinished) BOOL finished;
@property (nonatomic, copy, nonnull) SDAsyncBlock executionBlock; @property (nonatomic, copy, nonnull) SDAsyncBlock executionBlock;
@end @end
@implementation SDAsyncBlockOperation @implementation SDAsyncBlockOperation
@synthesize executing = _executing;
@synthesize finished = _finished;
- (nonnull instancetype)initWithBlock:(nonnull SDAsyncBlock)block { - (nonnull instancetype)initWithBlock:(nonnull SDAsyncBlock)block {
self = [super init]; self = [super init];
if (self) { if (self) {
@ -32,8 +35,12 @@
} }
- (void)start { - (void)start {
if (self.isCancelled) {
return;
}
[self willChangeValueForKey:@"isExecuting"]; [self willChangeValueForKey:@"isExecuting"];
self.isExecuting = YES; self.executing = YES;
[self didChangeValueForKey:@"isExecuting"]; [self didChangeValueForKey:@"isExecuting"];
if (self.executionBlock) { if (self.executionBlock) {
@ -43,11 +50,16 @@
} }
} }
- (void)cancel {
[super cancel];
[self complete];
}
- (void)complete { - (void)complete {
[self willChangeValueForKey:@"isExecuting"]; [self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"]; [self willChangeValueForKey:@"isFinished"];
self.isExecuting = NO; self.executing = NO;
self.isFinished = YES; self.finished = YES;
[self didChangeValueForKey:@"isExecuting"]; [self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"]; [self didChangeValueForKey:@"isFinished"];
} }

View File

@ -22,7 +22,8 @@
} }
@property (nonatomic, copy, readwrite) NSArray<NSURL *> *urls; @property (nonatomic, copy, readwrite) NSArray<NSURL *> *urls;
@property (nonatomic, strong) NSPointerArray *operations; @property (nonatomic, strong) NSPointerArray *loadOperations;
@property (nonatomic, strong) NSPointerArray *prefetchOperations;
@property (nonatomic, weak) SDWebImagePrefetcher *prefetcher; @property (nonatomic, weak) SDWebImagePrefetcher *prefetcher;
@property (nonatomic, copy, nullable) SDWebImagePrefetcherCompletionBlock completionBlock; @property (nonatomic, copy, nullable) SDWebImagePrefetcherCompletionBlock completionBlock;
@property (nonatomic, copy, nullable) SDWebImagePrefetcherProgressBlock progressBlock; @property (nonatomic, copy, nullable) SDWebImagePrefetcherProgressBlock progressBlock;
@ -93,7 +94,8 @@
token->_finishedCount = 0; token->_finishedCount = 0;
token->_totalCount = token.urls.count; token->_totalCount = token.urls.count;
atomic_flag_clear(&(token->_isAllFinished)); atomic_flag_clear(&(token->_isAllFinished));
token.operations = [NSPointerArray weakObjectsPointerArray]; token.loadOperations = [NSPointerArray weakObjectsPointerArray];
token.prefetchOperations = [NSPointerArray weakObjectsPointerArray];
token.progressBlock = progressBlock; token.progressBlock = progressBlock;
token.completionBlock = completionBlock; token.completionBlock = completionBlock;
[self addRunningToken:token]; [self addRunningToken:token];
@ -103,12 +105,12 @@
} }
- (void)startPrefetchWithToken:(SDWebImagePrefetchToken * _Nonnull)token { - (void)startPrefetchWithToken:(SDWebImagePrefetchToken * _Nonnull)token {
NSPointerArray *operations = token.operations; NSPointerArray *operations = token.loadOperations;
for (NSURL *url in token.urls) { for (NSURL *url in token.urls) {
__weak typeof(self) wself = self; __weak typeof(self) wself = self;
SDAsyncBlockOperation *prefetchOperation = [SDAsyncBlockOperation blockOperationWithBlock:^(SDAsyncBlockOperation * _Nonnull asyncOperation) { SDAsyncBlockOperation *prefetchOperation = [SDAsyncBlockOperation blockOperationWithBlock:^(SDAsyncBlockOperation * _Nonnull asyncOperation) {
__strong typeof(wself) strongSelf = wself; __strong typeof(wself) strongSelf = wself;
if (!strongSelf) { if (!strongSelf || asyncOperation.isCancelled) {
return; return;
} }
id<SDWebImageOperation> operation = [strongSelf.manager loadImageWithURL:url options:strongSelf.options context:strongSelf.context progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) { id<SDWebImageOperation> operation = [strongSelf.manager loadImageWithURL:url options:strongSelf.options context:strongSelf.context progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
@ -119,7 +121,6 @@
if (!finished) { if (!finished) {
return; return;
} }
[asyncOperation complete];
atomic_fetch_add_explicit(&(token->_finishedCount), 1, memory_order_relaxed); atomic_fetch_add_explicit(&(token->_finishedCount), 1, memory_order_relaxed);
if (error) { if (error) {
@ -137,11 +138,16 @@
[sself removeRunningToken:token]; [sself removeRunningToken:token];
} }
} }
[asyncOperation complete];
}]; }];
NSAssert(operation != nil, @"Operation should not be nil, [SDWebImageManager loadImageWithURL:options:context:progress:completed:] break prefetch logic");
@synchronized (token) { @synchronized (token) {
[operations addPointer:(__bridge void *)operation]; [operations addPointer:(__bridge void *)operation];
} }
}]; }];
@synchronized (token) {
[token.prefetchOperations addPointer:(__bridge void *)prefetchOperation];
}
[self.prefetchQueue addOperation:prefetchOperation]; [self.prefetchQueue addOperation:prefetchOperation];
} }
} }
@ -256,12 +262,21 @@
- (void)cancel { - (void)cancel {
@synchronized (self) { @synchronized (self) {
for (id operation in self.operations) { [self.prefetchOperations compact];
for (id operation in self.prefetchOperations) {
if ([operation conformsToProtocol:@protocol(SDWebImageOperation)]) { if ([operation conformsToProtocol:@protocol(SDWebImageOperation)]) {
[operation cancel]; [operation cancel];
} }
} }
self.operations.count = 0; self.prefetchOperations.count = 0;
[self.loadOperations compact];
for (id operation in self.loadOperations) {
if ([operation conformsToProtocol:@protocol(SDWebImageOperation)]) {
[operation cancel];
}
}
self.loadOperations.count = 0;
} }
self.completionBlock = nil; self.completionBlock = nil;
self.progressBlock = nil; self.progressBlock = nil;