Last active
September 18, 2024 05:13
-
-
Save rnapier/f513a58ec982ff4738b25afa465f6dda to your computer and use it in GitHub Desktop.
Regarding MainActor.run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// In regards to https://mastodon.social/@mattiem/112285978801305971 | |
// MainActor class with synchronous methods | |
@MainActor final class M { | |
func methodA() {} | |
func methodB() {} | |
} | |
// Actor that relies on M. | |
actor A { | |
func f() async { | |
// | |
// This is atomic | |
// | |
await MainActor.run { | |
m.methodA() | |
m.methodB() | |
} | |
print("M stuff is done.") | |
// | |
// This is not atomic | |
// | |
await m.methodA() | |
await m.methodB() // There is a suspension point between A and B | |
print("M stuff is done.") | |
// | |
// The equivalent to .run would be: | |
// | |
await Task { @MainActor in | |
m.methodA() | |
m.methodB() | |
}.value | |
print("M stuff is done.") | |
// I don't believe this approach is better than .run | |
// What **probably** is a better approach than either is making `M.methodAandB` | |
// to keep the operation atomic, and express it clearly. But if folks replace | |
// .run with Task, I think they're just shuffling syntax, and .run is clearer. | |
// It's easy to forget to add the `await` and `.value`, in which case the `print` | |
// happens too soon. | |
// | |
// I agree with Matt that it's possible A should be MainActor, but just because | |
// it happens to call M doesn't mean that's certain. | |
} | |
let m: M | |
init(m: M) { self.m = m } | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment