Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way of locking an object in Swift like in C#

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?

like image 779
Reynaldo Aguilar Avatar asked Apr 22 '15 16:04

Reynaldo Aguilar


People also ask

What is lock 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 ...

What is lock object in C#?

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.


Video Answer


2 Answers

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)
                }
            }

        }
    }
}
like image 83
YongUn Choi Avatar answered Sep 21 '22 23:09

YongUn Choi


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)
                    }
                }

            }
        }
    }
like image 22
Giordano Scalzo Avatar answered Sep 20 '22 23:09

Giordano Scalzo