If I'm in a callback function that is called by library code, and I need to return a value from a MainActor-isolated property, how can I get at it?
As a callback, I basically have no guarantees about what thread it will get called on. If I know I'm not on the main thread, I can do DispatchQueue.main.sync { ··· } and the compiler is happy.
But if I verify that I'm running on the main thread, how do I convince the compiler that I'm in the MainActor's context and can safely access isolated stuff?
I can't fire off a task with e.g. Task { @MainActor in ··· } because I have to wait for the task to finish and get me a result, and since I'm already on the main thread where that task would run, that's deadlock.
2 Likes
eskimo
(Quinn “The Eskimo!”)
2
I’d like to clarify your requirements here. Can you post some snippets of code that illustrate the issue?
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple
My specific case is that I'm working with libgit2, where I have things like git_remote_callbacks.git_indexer_progress_cb in which I can return a negative value to cancel.
eskimo
(Quinn “The Eskimo!”)
4
If sorry but I’m not familiar with that library. I was hoping to get a model of the problem, something that abstracts away the specific library details but is concrete enough to discuss the mechanics.
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple
saagarjha
(Saagar Jha)
5
I had this problem too. Here's what fell out of a previous discussions I had when trying to deal with this:
func unsafelyRunOnMainActor<T>(_ work: @MainActor () throws -> T) rethrows -> T {
return try _unsafelyRunOnMainActor(work)
}
@MainActor(unsafe)
func _unsafelyRunOnMainActor<T>(_ work: @MainActor () throws -> T) rethrows -> T {
try work()
}
This roundabout technique lets you (unsafely) tell Swift that you're on the MainActor already and would like to run code on it. (The specific context I needed this was a pre-concurrency protocol that I knew was @MainActor but not annotated as such, so I had to conform to it with nonisolated methods.)
2 Likes
As I understand it (from this post; I can't find any official docs), @MainActor(unsafe) is a transitionary thing that will do nothing in Swift 6.
1 Like