Rohan Bhale
Rohan Bhale

Reputation: 1345

Is there a elegant way to confine a class to a thread?

I have a class which I want to confine to a thread. To be precise I want it's void returning methods to be accessed on a certain thread or serial queue created by the class privately. To acheive this I looked at the NSManagedObjectContext API as a reference. There is a perform(block:() -> Void) method which can do this.

This comes with a code pattern that I am a bit uncomfortable. The user of this API needs to make calls to the object in the block of the perform(block:() -> Void) method. Is there a more elegant solution wherein I can declare that all methods and properties are confined to this particular thread. So essentially the user can access the methods but the internal operation happen on the intended thread.

I know the option where I can go to each method and dispatch work of that method into the intended thread. But this is an additional overhead to write the dispatch code.

Upvotes: 0

Views: 96

Answers (1)

user1046037
user1046037

Reputation: 17695

Approach:

Use a property wrapper

Code:

@propertyWrapper
struct QueueVariable<T> {

    private var _value  : T
    private let queue   : DispatchQueue

    var wrappedValue : T {

        get {
            queue.sync { _value }
        }

        set {
            queue.sync { _value = newValue }
        }
    }

    init(value: T,
         queue: DispatchQueue = DispatchQueue(label: "sync queue")) {
        _value      = value
        self.queue  = queue
    }
}

class Test {

    @QueueVariable(value: 100, queue: DispatchQueue(label: "aaa"))
    var a1

    @QueueVariable(value: "aaa")
    var a2
}

Invoking

Either pass the dispatch queue, or a new one would be generated.

let t1 = Test()

t1.a1 += 5

print(t1.a1)
print(t1.a2)

Upvotes: 1

Related Questions