I have the following code:
func foo() {
var sum = 0
var pendingElements = 10
for i in 0 ..< 10 {
proccessElementAsync(i) { value in
sum += value
pendingElements--
if pendingElements == 0 {
println(sum)
}
}
}
}
In this case the function proccessElementAsync
, as its name indicates, process its input parameter asynchronously and when it finishes it calls its corresponding completion handler.
The inconvenience with this approach is that since the variable pendingElements
is accessed through multiple threads, then it is possible that the statement if pendingElements == 0
will never has value true.
In C# we are able to do something like:
Object lockObject = new Object();
...
lock (lockObject) {
pendingElements--;
if (pendingElements == 0) {
Console.WriteLine(sum);
}
}
and this ensures that this variable will be accessed only for a thread at the same time. Is there any way of getting the same behavior in Swift?
The idea behind locks is that, you want to synchronize access to a part of your code, you create a lock (a token) that can be accessed by different threads, once a thread accesses that specific part of the code, it acquires that lock, and as long as the lock is acquired by a thread, other threads are blocked from ...
The lock statement acquires the mutual-exclusion lock for a given object, executes a statement block, and then releases the lock. While a lock is held, the thread that holds the lock can again acquire and release the lock. Any other thread is blocked from acquiring the lock and waits until the lock is released.
Hope this will help you.
func lock(obj: AnyObject, blk:() -> ()) {
objc_sync_enter(obj)
blk()
objc_sync_exit(obj)
}
var pendingElements = 10
func foo() {
var sum = 0
var pendingElements = 10
for i in 0 ..< 10 {
proccessElementAsync(i) { value in
lock(pendingElements) {
sum += value
pendingElements--
if pendingElements == 0 {
println(sum)
}
}
}
}
}
There is no native locking tools, but there are workarounds like explained in this SO question:
What is the Swift equivalent to Objective-C's "@synchronized"?
Using one of the answers, you can create a function:
func synchronize(lockObj: AnyObject!, closure: ()->()){
objc_sync_enter(lockObj)
closure()
objc_sync_exit(lockObj)
}
and then:
func foo() {
var sum = 0
var pendingElements = 10
for i in 0 ..< 10 {
processElementAsync(i) { value in
synchronize(pendingElements) {
sum += value
pendingElements--
if pendingElements == 0 {
println(sum)
}
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With