Skip to content

Commit

Permalink
Specify serial queue in init for multithreaded apps
Browse files Browse the repository at this point in the history
Previously, the code would use .global(qos: .userInitiated) to
specify which queue to use. This is a concurrent queue, so many
quick calls to functions in SwiftOCR can result in EXC_BAD_ACCESS
and other memory errors.

This does not change the behavior of SwiftOCR for users who do not
specifically opt into the fix by specifying a serial queue.

Specify a serial queue like the following in your client code to
opt in:

     let ocrQueue = DispatchQueue(label: "com.yourdomain.swiftocr")
     let ocr = SwiftOCR(dispatchQueue: ocrQueue)
  • Loading branch information
langford committed Aug 15, 2019
1 parent 3b299b7 commit 890eeae
Showing 1 changed file with 31 additions and 23 deletions.
54 changes: 31 additions & 23 deletions framework/SwiftOCR/SwiftOCR.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,27 +61,35 @@ open class SwiftOCR {

///All SwiftOCRRecognizedBlob from the last recognition
open var currentOCRRecognizedBlobs = [SwiftOCRRecognizedBlob]()


//MARK: Init
public init(){}

public init(recognizableCharacters: String, network: FFNN) {
self.characters = recognizableCharacters
self.network = network
}

public init(image: OCRImage, delegate: SwiftOCRDelegate?, _ completionHandler: @escaping (String) -> Void){
self.delegate = delegate
self.recognize(image, completionHandler)
}

public init(recognizableCharacters: String, network: FFNN, image: OCRImage, delegate: SwiftOCRDelegate?, _ completionHandler: @escaping (String) -> Void) {
self.characters = recognizableCharacters
self.network = network
self.delegate = delegate
self.recognize(image, completionHandler)
}

//Some applications will crash if called quickly in succession from double-free or other concurrency errors. Passing in a serial queue will prevent these crashes.
open var dispatchQueue:DispatchQueue

//MARK: Init
public init(dispatchQueue:DispatchQueue = DispatchQueue.global(qos: .userInitiated)){
self.dispatchQueue = dispatchQueue
}


public init(recognizableCharacters: String, network: FFNN,dispatchQueue:DispatchQueue = DispatchQueue.global(qos: .userInitiated)) {
self.dispatchQueue = dispatchQueue
self.characters = recognizableCharacters
self.network = network
}

public init(image: OCRImage, delegate: SwiftOCRDelegate?, dispatchQueue:DispatchQueue = DispatchQueue.global(qos: .userInitiated), _ completionHandler: @escaping (String) -> Void){
self.dispatchQueue = dispatchQueue
self.delegate = delegate
self.recognize(image, completionHandler)
}

public init(recognizableCharacters: String, network: FFNN, image: OCRImage, delegate: SwiftOCRDelegate?, dispatchQueue:DispatchQueue = DispatchQueue.global(qos: .userInitiated), _ completionHandler: @escaping (String) -> Void) {
self.dispatchQueue = dispatchQueue
self.characters = recognizableCharacters
self.network = network
self.delegate = delegate
self.recognize(image, completionHandler)
}

/**
Expand All @@ -105,7 +113,7 @@ open class SwiftOCR {
return whiteList && blackList
}

DispatchQueue.global(qos: .userInitiated).async {
dispatchQueue.async {
let preprocessedImage = self.delegate?.preprocessImageForOCR(image) ?? self.preprocessImageForOCR(image)

let blobs = self.extractBlobs(preprocessedImage)
Expand Down Expand Up @@ -179,7 +187,7 @@ open class SwiftOCR {
*/

open func recognizeInRect(_ image: OCRImage, rect: CGRect, completionHandler: @escaping (String) -> Void){
DispatchQueue.global(qos: .userInitiated).async {
dispatchQueue.async {
#if os(iOS)
let cgImage = image.cgImage
let croppedCGImage = cgImage?.cropping(to: rect)!
Expand Down

0 comments on commit 890eeae

Please sign in to comment.