Use thread safe manager store dictionary (#864)

Fix crash due to concurrent access of managerStore dictionary.
Swift2 and Swift3 had been enhanced respectively with the following
pull requests: #3873 #5610
This commit is contained in:
marcotta 2018-08-21 20:27:40 +02:00 committed by William Cheng
parent cbf61d5524
commit bb2712fe45
2 changed files with 64 additions and 6 deletions

View File

@ -17,8 +17,37 @@ class AlamofireRequestBuilderFactory: RequestBuilderFactory {
}
}
private struct SynchronizedDictionary<K: Hashable, V> {
private var dictionary = [K: V]()
private let queue = DispatchQueue(
label: "SynchronizedDictionary",
qos: DispatchQoS.userInitiated,
attributes: [DispatchQueue.Attributes.concurrent],
autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.inherit,
target: nil
)
public subscript(key: K) -> V? {
get {
var value: V?
queue.sync {
value = self.dictionary[key]
}
return value
}
set {
queue.sync(flags: DispatchWorkItemFlags.barrier) {
self.dictionary[key] = newValue
}
}
}
}
// Store manager to retain its reference
private var managerStore: [String: Alamofire.SessionManager] = [:]
private var managerStore = SynchronizedDictionary<String, Alamofire.SessionManager>()
open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
required public init(method: String, URLString: String, parameters: [String : Any]?, isBody: Bool, headers: [String : String] = [:]) {
@ -112,7 +141,7 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
}
let cleanupRequest = {
_ = managerStore.removeValue(forKey: managerId)
managerStore[managerId] = nil
}
let validatedRequest = request.validate()
@ -314,7 +343,7 @@ open class AlamofireDecodableRequestBuilder<T:Decodable>: AlamofireRequestBuilde
}
let cleanupRequest = {
_ = managerStore.removeValue(forKey: managerId)
managerStore[managerId] = nil
}
let validatedRequest = request.validate()

View File

@ -17,8 +17,37 @@ class AlamofireRequestBuilderFactory: RequestBuilderFactory {
}
}
private struct SynchronizedDictionary<K: Hashable, V> {
private var dictionary = [K: V]()
private let queue = DispatchQueue(
label: "SynchronizedDictionary",
qos: DispatchQoS.userInitiated,
attributes: [DispatchQueue.Attributes.concurrent],
autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.inherit,
target: nil
)
public subscript(key: K) -> V? {
get {
var value: V?
queue.sync {
value = self.dictionary[key]
}
return value
}
set {
queue.sync(flags: DispatchWorkItemFlags.barrier) {
self.dictionary[key] = newValue
}
}
}
}
// Store manager to retain its reference
private var managerStore: [String: Alamofire.SessionManager] = [:]
private var managerStore = SynchronizedDictionary<String, Alamofire.SessionManager>()
open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
required public init(method: String, URLString: String, parameters: [String : Any]?, isBody: Bool, headers: [String : String] = [:]) {
@ -112,7 +141,7 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
}
let cleanupRequest = {
_ = managerStore.removeValue(forKey: managerId)
managerStore[managerId] = nil
}
let validatedRequest = request.validate()
@ -314,7 +343,7 @@ open class AlamofireDecodableRequestBuilder<T:Decodable>: AlamofireRequestBuilde
}
let cleanupRequest = {
_ = managerStore.removeValue(forKey: managerId)
managerStore[managerId] = nil
}
let validatedRequest = request.validate()