mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
refactor(mobile): IOS replace DispatchQueue + DispatchSemaphore with OperationQueue for image processing (#27471)
refactor: replace DispatchQueue + DispatchSemaphore with OperationQueue for image processing
This commit is contained in:
@@ -1,7 +1,12 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum ImageProcessing {
|
enum ImageProcessing {
|
||||||
static let queue = DispatchQueue(label: "thumbnail.processing", qos: .userInitiated, attributes: .concurrent)
|
static let queue = {
|
||||||
static let semaphore = DispatchSemaphore(value: ProcessInfo.processInfo.activeProcessorCount * 2)
|
let q = OperationQueue()
|
||||||
|
q.name = "thumbnail.processing"
|
||||||
|
q.qualityOfService = .userInitiated
|
||||||
|
q.maxConcurrentOperationCount = ProcessInfo.processInfo.activeProcessorCount * 2
|
||||||
|
return q
|
||||||
|
}()
|
||||||
static let cancelledResult = Result<[String: Int64]?, any Error>.success(nil)
|
static let cancelledResult = Result<[String: Int64]?, any Error>.success(nil)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import MobileCoreServices
|
|||||||
import Photos
|
import Photos
|
||||||
|
|
||||||
class LocalImageRequest {
|
class LocalImageRequest {
|
||||||
weak var workItem: DispatchWorkItem?
|
weak var operation: Operation?
|
||||||
var isCancelled = false
|
var isCancelled = false
|
||||||
let callback: (Result<[String: Int64]?, any Error>) -> Void
|
let callback: (Result<[String: Int64]?, any Error>) -> Void
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ class LocalImageApiImpl: LocalImageApi {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
func getThumbhash(thumbhash: String, completion: @escaping (Result<[String : Int64], any Error>) -> Void) {
|
func getThumbhash(thumbhash: String, completion: @escaping (Result<[String : Int64], any Error>) -> Void) {
|
||||||
ImageProcessing.queue.async {
|
ImageProcessing.queue.addOperation {
|
||||||
guard let data = Data(base64Encoded: thumbhash)
|
guard let data = Data(base64Encoded: thumbhash)
|
||||||
else { return completion(.failure(PigeonError(code: "", message: "Invalid base64 string: \(thumbhash)", details: nil)))}
|
else { return completion(.failure(PigeonError(code: "", message: "Invalid base64 string: \(thumbhash)", details: nil)))}
|
||||||
|
|
||||||
@@ -66,16 +66,7 @@ class LocalImageApiImpl: LocalImageApi {
|
|||||||
|
|
||||||
func requestImage(assetId: String, requestId: Int64, width: Int64, height: Int64, isVideo: Bool, preferEncoded: Bool, completion: @escaping (Result<[String: Int64]?, any Error>) -> Void) {
|
func requestImage(assetId: String, requestId: Int64, width: Int64, height: Int64, isVideo: Bool, preferEncoded: Bool, completion: @escaping (Result<[String: Int64]?, any Error>) -> Void) {
|
||||||
let request = LocalImageRequest(callback: completion)
|
let request = LocalImageRequest(callback: completion)
|
||||||
let item = DispatchWorkItem {
|
let operation = BlockOperation {
|
||||||
if request.isCancelled {
|
|
||||||
return completion(ImageProcessing.cancelledResult)
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageProcessing.semaphore.wait()
|
|
||||||
defer {
|
|
||||||
ImageProcessing.semaphore.signal()
|
|
||||||
}
|
|
||||||
|
|
||||||
if request.isCancelled {
|
if request.isCancelled {
|
||||||
return completion(ImageProcessing.cancelledResult)
|
return completion(ImageProcessing.cancelledResult)
|
||||||
}
|
}
|
||||||
@@ -180,9 +171,9 @@ class LocalImageApiImpl: LocalImageApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
request.workItem = item
|
request.operation = operation
|
||||||
Self.add(requestId: requestId, request: request)
|
Self.add(requestId: requestId, request: request)
|
||||||
ImageProcessing.queue.async(execute: item)
|
ImageProcessing.queue.addOperation(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cancelRequest(requestId: Int64) {
|
func cancelRequest(requestId: Int64) {
|
||||||
@@ -201,8 +192,8 @@ class LocalImageApiImpl: LocalImageApi {
|
|||||||
requestQueue.async {
|
requestQueue.async {
|
||||||
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 operation = request.operation else { return }
|
||||||
if item.isCancelled {
|
if operation.isCancelled {
|
||||||
cancelQueue.async { request.callback(ImageProcessing.cancelledResult) }
|
cancelQueue.async { request.callback(ImageProcessing.cancelledResult) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,10 +73,7 @@ class RemoteImageApiImpl: NSObject, RemoteImageApi {
|
|||||||
return request.completion(.failure(PigeonError(code: "", message: "No data received", details: nil)))
|
return request.completion(.failure(PigeonError(code: "", message: "No data received", details: nil)))
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageProcessing.queue.async {
|
ImageProcessing.queue.addOperation {
|
||||||
ImageProcessing.semaphore.wait()
|
|
||||||
defer { ImageProcessing.semaphore.signal() }
|
|
||||||
|
|
||||||
if request.isCancelled {
|
if request.isCancelled {
|
||||||
return request.completion(ImageProcessing.cancelledResult)
|
return request.completion(ImageProcessing.cancelledResult)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user