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

View File

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