From c60e6714dd34af904065bad943ea868dbd3a40b2 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Tue, 27 Dec 2022 17:24:07 +0800 Subject: [PATCH] Added `ioQueueAttributes` to use concurrent or control QoS for image cache internal IO Queue --- SDWebImage/Core/SDImageCache.m | 8 +++++--- SDWebImage/Core/SDImageCacheConfig.h | 9 +++++++++ SDWebImage/Core/SDImageCacheConfig.m | 3 +++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/SDWebImage/Core/SDImageCache.m b/SDWebImage/Core/SDImageCache.m index 94e2cd77..5d3c39cb 100644 --- a/SDWebImage/Core/SDImageCache.m +++ b/SDWebImage/Core/SDImageCache.m @@ -109,14 +109,16 @@ static NSString * _defaultDiskCacheDirectory; if ((self = [super init])) { NSAssert(ns, @"Cache namespace should not be nil"); - // Create IO serial queue - _ioQueue = dispatch_queue_create("com.hackemist.SDImageCache", DISPATCH_QUEUE_SERIAL); - if (!config) { config = SDImageCacheConfig.defaultCacheConfig; } _config = [config copy]; + // Create IO queue + dispatch_queue_attr_t ioQueueAttributes = _config.ioQueueAttributes; + _ioQueue = dispatch_queue_create("com.hackemist.SDImageCache", ioQueueAttributes); + NSAssert(_ioQueue, @"The IO queue should not be nil. Your configured `ioQueueAttributes` may be wrong"); + // Init the memory cache NSAssert([config.memoryCacheClass conformsToProtocol:@protocol(SDMemoryCache)], @"Custom memory cache class must conform to `SDMemoryCache` protocol"); _memoryCache = [[config.memoryCacheClass alloc] initWithConfig:_config]; diff --git a/SDWebImage/Core/SDImageCacheConfig.h b/SDWebImage/Core/SDImageCacheConfig.h index 468fa09e..7e53ac7d 100644 --- a/SDWebImage/Core/SDImageCacheConfig.h +++ b/SDWebImage/Core/SDImageCacheConfig.h @@ -127,6 +127,15 @@ typedef NS_ENUM(NSUInteger, SDImageCacheConfigExpireType) { */ @property (strong, nonatomic, nullable) NSFileManager *fileManager; +/** + * The dispatch queue attr for ioQueue. You can config the QoS and concurrent/serial to internal IO queue. The ioQueue is used by SDImageCache to access read/write for disk data. + * Defaults we use `DISPATCH_QUEUE_SERIAL`(NULL), to use serial dispatch queue to ensure single access for disk data. It's safe but may be slow. + * @note You can override this to use `DISPATCH_QUEUE_CONCURRENT`, use concurrent queue. + * @warning **MAKE SURE** to keep `diskCacheWritingOptions` to use `NSDataWritingAtomic`, or concurrent queue may cause corrupted disk data (because multiple threads read/write same file without atomic is not IO-safe). + * @note This value does not support dynamic changes. Which means further modification on this value after cache initialized has no effect. + */ +@property (strong, nonatomic, nullable) dispatch_queue_attr_t ioQueueAttributes; + /** * The custom memory cache class. Provided class instance must conform to `SDMemoryCache` protocol to allow usage. * Defaults to built-in `SDMemoryCache` class. diff --git a/SDWebImage/Core/SDImageCacheConfig.m b/SDWebImage/Core/SDImageCacheConfig.m index fc022859..ee6db59d 100644 --- a/SDWebImage/Core/SDImageCacheConfig.m +++ b/SDWebImage/Core/SDImageCacheConfig.m @@ -35,6 +35,8 @@ static const NSInteger kDefaultCacheMaxDiskAge = 60 * 60 * 24 * 7; // 1 week _maxDiskAge = kDefaultCacheMaxDiskAge; _maxDiskSize = 0; _diskCacheExpireType = SDImageCacheConfigExpireTypeModificationDate; + _fileManager = nil; + _ioQueueAttributes = DISPATCH_QUEUE_SERIAL; // NULL _memoryCacheClass = [SDMemoryCache class]; _diskCacheClass = [SDDiskCache class]; } @@ -56,6 +58,7 @@ static const NSInteger kDefaultCacheMaxDiskAge = 60 * 60 * 24 * 7; // 1 week config.maxMemoryCount = self.maxMemoryCount; config.diskCacheExpireType = self.diskCacheExpireType; config.fileManager = self.fileManager; // NSFileManager does not conform to NSCopying, just pass the reference + config.ioQueueAttributes = self.ioQueueAttributes; // Pass the reference config.memoryCacheClass = self.memoryCacheClass; config.diskCacheClass = self.diskCacheClass;