#if canImport(Darwin) import Darwin import CoreFoundation // MARK: - Darwin main-queue pump /// Drains Swift's default `MainActor` executor by periodically running the /// process's `CFRunLoop` from inside the GLib main loop. /// /// ## Why this exists /// /// On Linux, ``GLibMainExecutor`` is installed as the literal process main /// executor via the stdlib's `@_spi(ExperimentalCustomExecutors)` API, so /// every `Task { }` and `await` resumption is driven directly by GLib idle /// sources. That SPI has no accessible implementation on Apple platforms: /// `_Concurrency` is an OS-vended, library-evolution (resilient) framework /// there, and Apple ships only its public `.swiftinterface` - `@_spi` /// declarations require a `.private.swiftinterface`, which no distributed /// Xcode or Command Line Tools install carries for this module. There is no /// stable substitute for overriding what backs `MainActor` on Darwin today. /// /// So on Darwin, `MainActor` keeps the stdlib's default executor, which is /// backed by the main dispatch queue. GTK's own macOS backend /// (`gdkmacoseventsource.c`) keeps GLib's poll-based main loop primary and /// pulls native Cocoa events into it via a replaced `GPollFunc` - it does not /// hand control to `CFRunLoop`. That means `Adw.Application.run` blocks the /// thread inside GLib's loop exactly as it does on Linux, and the main /// dispatch queue is never given a chance to run on its own. /// /// This pump closes that gap without reaching for any private or /// experimental API: a low-priority, always-repeating `Timeout` source drains /// `CFRunLoopRunInMode` a few times per GLib iteration. Draining the run loop /// in `.defaultMode` is what services the main dispatch queue on every Apple /// platform (it is the same mechanism `RunLoop.main.run()` relies on), so any /// `Task { @MainActor in }` continuation queued by the stdlib's default /// executor gets a chance to run within one pump interval. Synchronous GTK /// signal/source callbacks are unaffected either way: those already reach /// `@MainActor` code through `MainActor.assumeIsolated`, which asserts /// same-thread isolation rather than routing through an executor, so they /// have never depended on which executor backs `MainActor`. @_spi(Portico) @MainActor public enum DarwinMainQueuePump { /// How often the pump drains the run loop. Short enough that `await` /// resumption feels immediate against a 60-120Hz UI; long enough that the /// idle cost is negligible (`CFRunLoopRunInMode` returns immediately when /// nothing is pending). private static let interval = Duration.milliseconds(4) /// Guards the `Timeout` attach; the lazy static makes repeat calls free /// so it is safe to call ``install()`` more than once. private static let installOnce: Bool = { Timeout(interval: DarwinMainQueuePump.interval, priority: .default, repeats: true) { // `.defaultMode` is the mode `RunLoop.main`/`CFRunLoopRun()` use // by default and the one the main dispatch queue's run-loop // source is registered against. Loop until the run loop reports // nothing left to do, so a burst of queued continuations drains // in one GLib tick rather than trickling out one per `interval`. while CFRunLoopRunInMode(.defaultMode, 0, true) == .handledSource {} } return true }() /// Starts draining the main dispatch queue from the GLib main loop if it /// has not already been started this process lifetime. Idempotent; call /// before ``Adw/Application/run(argv:)`` blocks the thread. @_spi(Portico) public static func install() { _ = installOnce } } #endif