Reputation: 19124
Given the code below from a class:
cancellable = input
.receive(on: scheduler)
.map { ... }
.sink(receiveValue: { value in
self.state = value
})
where input
is a PassthroughSubject.
Now, when scheduler
is the main queue or the RunLoop.main AND input will be called from the main thread, does receive(on: scheduler)
programmatically optimise away an explicit dispatch to the main queue?
So, basically something like this:
if Thread.isMainThread {
/* execute closure */
} else {
/* dispatch closure async to main */
}
The documentation for receive(on:)
gives a vague hint, that it might perform some optimisations:
"Prefer receive(on:options:) over explicit use of dispatch queues"
pub.sink {
DispatchQueue.main.async {
// Do something.
}
}
Upvotes: 6
Views: 1367
Reputation: 385890
No, receive(on:)
does not optimize away the dispatch. Doing so could lead to a deadlock. Example:
let l = Lock()
let cancellable = input
.receive(on: scheduler)
.map { ... }
.sink(receiveValue: { value in
l.lock()
self.state = value
l.unlock()
})
l.lock()
input.send(1)
l.unlock()
If the dispatch were eliminated, this example would try to lock the already-locked lock l
, and hang (or crash if it can detect the deadlock).
Upvotes: 3
Reputation: 15238
Looking at the sources for RunLoop and DispatchQueue, it doesn't look like there is such an optimisation in their conformance to the Scheduler
protocol.
But to be fair, there might be lower level optimisations at play.
Upvotes: 2