Last active
October 23, 2023 20:46
-
-
Save ole/10a832ab2388163099841d683cfed102 to your computer and use it in GitHub Desktop.
A reimplementation of the basics of MainActor. Sample code for https://oleb.net/2022/how-mainactor-works/
This file contains hidden or 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
import Dispatch | |
@globalActor | |
final actor MyMainActor { | |
// Don’t allow others to create instances | |
private init() {} | |
// Requirements from the implicit GlobalActor conformance | |
typealias ActorType = MyMainActor | |
static var shared: ActorType = MyMainActor() | |
static var sharedUnownedExecutor: UnownedSerialExecutor { | |
mainExecutor.asUnownedSerialExecutor() | |
} | |
// Requirement from the implicit Actor conformance | |
nonisolated var unownedExecutor: UnownedSerialExecutor { | |
mainExecutor.asUnownedSerialExecutor() | |
} | |
} | |
// Store main executor in a global to keep it alive | |
private let mainExecutor = MainExecutor() | |
final class MainExecutor: SerialExecutor { | |
func asUnownedSerialExecutor() -> UnownedSerialExecutor { | |
UnownedSerialExecutor(ordinary: self) | |
} | |
func enqueue(_ job: UnownedJob) { | |
DispatchQueue.main.async { | |
job._runSynchronously(on: self.asUnownedSerialExecutor()) | |
} | |
} | |
} | |
// MARK: - Usage example | |
import Foundation | |
actor SomeActor { | |
func f() async { | |
assert(!Thread.isMainThread) | |
await mainA() | |
assert(!Thread.isMainThread) | |
} | |
} | |
@MyMainActor | |
func mainA() { | |
assert(Thread.isMainThread) | |
} | |
@main struct Main { | |
static func main() async { | |
await SomeActor().f() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment