Skip to content

Commit bb2712f

Browse files
marcottawing328
authored andcommitted
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
1 parent cbf61d5 commit bb2712f

2 files changed

Lines changed: 64 additions & 6 deletions

File tree

modules/openapi-generator/src/main/resources/swift4/AlamofireImplementations.mustache

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,37 @@ class AlamofireRequestBuilderFactory: RequestBuilderFactory {
1717
}
1818
}
1919

20+
private struct SynchronizedDictionary<K: Hashable, V> {
21+
22+
private var dictionary = [K: V]()
23+
private let queue = DispatchQueue(
24+
label: "SynchronizedDictionary",
25+
qos: DispatchQoS.userInitiated,
26+
attributes: [DispatchQueue.Attributes.concurrent],
27+
autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.inherit,
28+
target: nil
29+
)
30+
31+
public subscript(key: K) -> V? {
32+
get {
33+
var value: V?
34+
35+
queue.sync {
36+
value = self.dictionary[key]
37+
}
38+
39+
return value
40+
}
41+
set {
42+
queue.sync(flags: DispatchWorkItemFlags.barrier) {
43+
self.dictionary[key] = newValue
44+
}
45+
}
46+
}
47+
}
48+
2049
// Store manager to retain its reference
21-
private var managerStore: [String: Alamofire.SessionManager] = [:]
50+
private var managerStore = SynchronizedDictionary<String, Alamofire.SessionManager>()
2251

2352
open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
2453
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> {
112141
}
113142

114143
let cleanupRequest = {
115-
_ = managerStore.removeValue(forKey: managerId)
144+
managerStore[managerId] = nil
116145
}
117146

118147
let validatedRequest = request.validate()
@@ -314,7 +343,7 @@ open class AlamofireDecodableRequestBuilder<T:Decodable>: AlamofireRequestBuilde
314343
}
315344

316345
let cleanupRequest = {
317-
_ = managerStore.removeValue(forKey: managerId)
346+
managerStore[managerId] = nil
318347
}
319348

320349
let validatedRequest = request.validate()

samples/client/petstore/swift4/default/PetstoreClient/Classes/OpenAPIs/AlamofireImplementations.swift

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,37 @@ class AlamofireRequestBuilderFactory: RequestBuilderFactory {
1717
}
1818
}
1919

20+
private struct SynchronizedDictionary<K: Hashable, V> {
21+
22+
private var dictionary = [K: V]()
23+
private let queue = DispatchQueue(
24+
label: "SynchronizedDictionary",
25+
qos: DispatchQoS.userInitiated,
26+
attributes: [DispatchQueue.Attributes.concurrent],
27+
autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.inherit,
28+
target: nil
29+
)
30+
31+
public subscript(key: K) -> V? {
32+
get {
33+
var value: V?
34+
35+
queue.sync {
36+
value = self.dictionary[key]
37+
}
38+
39+
return value
40+
}
41+
set {
42+
queue.sync(flags: DispatchWorkItemFlags.barrier) {
43+
self.dictionary[key] = newValue
44+
}
45+
}
46+
}
47+
}
48+
2049
// Store manager to retain its reference
21-
private var managerStore: [String: Alamofire.SessionManager] = [:]
50+
private var managerStore = SynchronizedDictionary<String, Alamofire.SessionManager>()
2251

2352
open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
2453
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> {
112141
}
113142

114143
let cleanupRequest = {
115-
_ = managerStore.removeValue(forKey: managerId)
144+
managerStore[managerId] = nil
116145
}
117146

118147
let validatedRequest = request.validate()
@@ -314,7 +343,7 @@ open class AlamofireDecodableRequestBuilder<T:Decodable>: AlamofireRequestBuilde
314343
}
315344

316345
let cleanupRequest = {
317-
_ = managerStore.removeValue(forKey: managerId)
346+
managerStore[managerId] = nil
318347
}
319348

320349
let validatedRequest = request.validate()

0 commit comments

Comments
 (0)