diff --git a/SDWebImage/Core/SDWebImageManager.m b/SDWebImage/Core/SDWebImageManager.m index 3b29632d..d5be68f6 100644 --- a/SDWebImage/Core/SDWebImageManager.m +++ b/SDWebImage/Core/SDWebImageManager.m @@ -17,7 +17,9 @@ static id _defaultImageCache; static id _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 (strong, nonatomic, readwrite, nullable) id loaderOperation; @@ -803,22 +805,38 @@ static id _defaultImageLoader; @implementation SDWebImageCombinedOperation -- (void)cancel { - @synchronized(self) { - if (self.isCancelled) { - return; - } - self.cancelled = YES; - if (self.cacheOperation) { - [self.cacheOperation cancel]; - self.cacheOperation = nil; - } - if (self.loaderOperation) { - [self.loaderOperation cancel]; - self.loaderOperation = nil; - } - [self.manager safelyRemoveOperationFromRunning:self]; +- (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 { + SD_LOCK(_cancelledLock); + if (_cancelled) { + return; + } + _cancelled = YES; + if (self.cacheOperation) { + [self.cacheOperation cancel]; + self.cacheOperation = nil; + } + if (self.loaderOperation) { + [self.loaderOperation cancel]; + self.loaderOperation = nil; + } + [self.manager safelyRemoveOperationFromRunning:self]; + SD_UNLOCK(_cancelledLock); } @end