Reputation: 25964
Will the following create a possible race condition?
let syncGroup = DispatchGroup()
var tempData: [Int]
for index in 1...10 {
syncGroup.enter()
// Alamofire is being called in the following.
// I am leaving out implementation, just to simplify.
asyncTaskUsingAlamofire(completionHandler: { (data: [Data]) in
// Possible race condition?
// Should I use something like `sync()` and how?
tempData.append(data)
syncGroup.leave()
})
}
syncGroup.notify(queue: .main) {
// We can go on, all data is added to tempData
}
I can see that swift has a sync()
If and how would you solve this?
Upvotes: 2
Views: 792
Reputation: 130092
You should make sure that all completion handlers are called on the same queue. If they are not called on the same queue, they can be called simultaneously, creating a race condition.
If you are not sure whether the completion handler is called on a specific queue, you can simply insert an .async
wrapper:
asyncTaskUsingAlamofire(completionHandler: { (data: [Data]) in
DispatchQueue.main.async {
tempData.append(data)
syncGroup.leave()
}
}
However, Alamofire is always executing callbacks on the main
queue, therefore no race conditions should happen and your solution is safe.
Upvotes: 1
Reputation: 59496
Very similar to Sulthan's answer, I just usually use custom serial queue
for this scenario
let group = DispatchGroup()
var results = [Int]()
let serialQueue = DispatchQueue(label: "serialQueue")
for _ in 1...10 {
group.enter()
asyncTaskUsingAlamofire { data in
serialQueue.async {
// Multiple instances of this block will be executed into a serial queue
// So max 1 block at a time
// This means results is accessed safely
results.append(contentsOf: data)
group.leave()
}
}
}
group.notify(queue: .main) {
print(results)
}
The results
array is safely accessed because every instance of the block that mutate it
results.append(contentsOf: data)
group.leave()
is executed inside a Serial Queue.
serialQueue.async {
results.append(contentsOf: data)
group.leave()
}
In other words the 10 instances of the block are enqueued into serialQueue
and executed one at a time.
This does guarantee a safe access of results
.
Upvotes: 4