separate asset and thumbnail concurrency
This commit is contained in:
@@ -40,7 +40,8 @@ class ThumbnailApiImpl: ThumbnailApi {
|
|||||||
private static let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue).rawValue
|
private static let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue).rawValue
|
||||||
private static var requests = [Int64: Request]()
|
private static var requests = [Int64: Request]()
|
||||||
private static let cancelledResult = Result<[String: Int64], any Error>.success([:])
|
private static let cancelledResult = Result<[String: Int64], any Error>.success([:])
|
||||||
private static let concurrencySemaphore = DispatchSemaphore(value: ProcessInfo.processInfo.activeProcessorCount * 2)
|
private static let assetConcurrencySemaphore = DispatchSemaphore(value: ProcessInfo.processInfo.activeProcessorCount * 2)
|
||||||
|
private static let thumbnailConcurrencySemaphore = DispatchSemaphore(value: ProcessInfo.processInfo.activeProcessorCount / 2 + 1)
|
||||||
private static let assetCache = {
|
private static let assetCache = {
|
||||||
let assetCache = NSCache<NSString, PHAsset>()
|
let assetCache = NSCache<NSString, PHAsset>()
|
||||||
assetCache.countLimit = 10000
|
assetCache.countLimit = 10000
|
||||||
@@ -82,22 +83,19 @@ class ThumbnailApiImpl: ThumbnailApi {
|
|||||||
return completion(Self.cancelledResult)
|
return completion(Self.cancelledResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
Self.concurrencySemaphore.wait()
|
guard let asset = Self.requestAsset(request: request, assetId: assetId)
|
||||||
defer {
|
else {
|
||||||
Self.concurrencySemaphore.signal()
|
|
||||||
}
|
|
||||||
|
|
||||||
if request.isCancelled {
|
if request.isCancelled {
|
||||||
return completion(Self.cancelledResult)
|
return completion(Self.cancelledResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let asset = Self.requestAsset(assetId: assetId)
|
|
||||||
else {
|
|
||||||
Self.removeRequest(requestId: requestId)
|
Self.removeRequest(requestId: requestId)
|
||||||
completion(.failure(PigeonError(code: "", message: "Could not get asset data for \(assetId)", details: nil)))
|
completion(.failure(PigeonError(code: "", message: "Could not get asset data for \(assetId)", details: nil)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Self.thumbnailConcurrencySemaphore.wait()
|
||||||
|
defer { Self.thumbnailConcurrencySemaphore.signal() }
|
||||||
|
|
||||||
if request.isCancelled {
|
if request.isCancelled {
|
||||||
return completion(Self.cancelledResult)
|
return completion(Self.cancelledResult)
|
||||||
}
|
}
|
||||||
@@ -187,17 +185,25 @@ class ThumbnailApiImpl: ThumbnailApi {
|
|||||||
guard let request = requests.removeValue(forKey: requestId) else { return }
|
guard let request = requests.removeValue(forKey: requestId) else { return }
|
||||||
request.isCancelled = true
|
request.isCancelled = true
|
||||||
guard let item = request.workItem else { return }
|
guard let item = request.workItem else { return }
|
||||||
|
item.cancel()
|
||||||
if item.isCancelled {
|
if item.isCancelled {
|
||||||
cancelQueue.async { request.callback(Self.cancelledResult) }
|
cancelQueue.async { request.callback(Self.cancelledResult) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func requestAsset(assetId: String) -> PHAsset? {
|
private static func requestAsset(request: Request, assetId: String) -> PHAsset? {
|
||||||
var asset: PHAsset?
|
var asset: PHAsset?
|
||||||
assetQueue.sync { asset = assetCache.object(forKey: assetId as NSString) }
|
assetQueue.sync { asset = assetCache.object(forKey: assetId as NSString) }
|
||||||
if asset != nil { return asset }
|
if asset != nil { return asset }
|
||||||
|
|
||||||
|
Self.assetConcurrencySemaphore.wait()
|
||||||
|
defer { Self.assetConcurrencySemaphore.signal() }
|
||||||
|
|
||||||
|
if request.isCancelled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
guard let asset = PHAsset.fetchAssets(withLocalIdentifiers: [assetId], options: Self.fetchOptions).firstObject
|
guard let asset = PHAsset.fetchAssets(withLocalIdentifiers: [assetId], options: Self.fetchOptions).firstObject
|
||||||
else { return nil }
|
else { return nil }
|
||||||
assetQueue.async { assetCache.setObject(asset, forKey: assetId as NSString) }
|
assetQueue.async { assetCache.setObject(asset, forKey: assetId as NSString) }
|
||||||
|
|||||||
Reference in New Issue
Block a user