Synchronise getter and setter of the cancelled property of the SDWebImageCombinedOperation in order to eliminate data race.

This commit is contained in:
Alexander Gaidukov 2022-09-05 16:32:32 +07:00
parent 3e48cb68d8
commit 5a18c84529
1 changed files with 34 additions and 16 deletions

View File

@ -17,7 +17,9 @@
static id<SDImageCache> _defaultImageCache; static id<SDImageCache> _defaultImageCache;
static id<SDImageLoader> _defaultImageLoader; static id<SDImageLoader> _defaultImageLoader;
@interface SDWebImageCombinedOperation () @interface SDWebImageCombinedOperation () {
SD_LOCK_DECLARE(_cancelledLock); // a lock to keep the access to `cancelled` thread-safe
}
@property (assign, nonatomic, getter = isCancelled) BOOL cancelled; @property (assign, nonatomic, getter = isCancelled) BOOL cancelled;
@property (strong, nonatomic, readwrite, nullable) id<SDWebImageOperation> loaderOperation; @property (strong, nonatomic, readwrite, nullable) id<SDWebImageOperation> loaderOperation;
@ -803,12 +805,28 @@ static id<SDImageLoader> _defaultImageLoader;
@implementation SDWebImageCombinedOperation @implementation SDWebImageCombinedOperation
- (instancetype)init {
if (self = [super init]) {
SD_LOCK_INIT(_cancelledLock);
}
return self;
}
- (BOOL)isCancelled {
BOOL isCancelled = NO;
SD_LOCK(_cancelledLock);
isCancelled = _cancelled;
SD_UNLOCK(_cancelledLock);
return isCancelled;
}
- (void)cancel { - (void)cancel {
@synchronized(self) { SD_LOCK(_cancelledLock);
if (self.isCancelled) { if (_cancelled) {
return; return;
} }
self.cancelled = YES; _cancelled = YES;
if (self.cacheOperation) { if (self.cacheOperation) {
[self.cacheOperation cancel]; [self.cacheOperation cancel];
self.cacheOperation = nil; self.cacheOperation = nil;
@ -818,7 +836,7 @@ static id<SDImageLoader> _defaultImageLoader;
self.loaderOperation = nil; self.loaderOperation = nil;
} }
[self.manager safelyRemoveOperationFromRunning:self]; [self.manager safelyRemoveOperationFromRunning:self];
} SD_UNLOCK(_cancelledLock);
} }
@end @end