From 47016517a63d6823d6b49ea910dfa0f10414f738 Mon Sep 17 00:00:00 2001 From: Rachel Brindle Date: Wed, 1 Oct 2025 09:37:10 -0700 Subject: [PATCH 1/2] Revert "Remove duplicated runloop code (#1193)" This reverts commit ae0648d7c75d908b824f406601b91edb2d7809ff. --- Sources/Nimble/Utils/AsyncAwait.swift | 4 ++ Sources/Nimble/Utils/AsyncTimerSequence.swift | 3 + Sources/Nimble/Utils/PollAwait.swift | 70 ++++++++++++------- Tests/NimbleTests/PollingTest+Require.swift | 3 + 4 files changed, 55 insertions(+), 25 deletions(-) diff --git a/Sources/Nimble/Utils/AsyncAwait.swift b/Sources/Nimble/Utils/AsyncAwait.swift index c23dd13dc..000e84886 100644 --- a/Sources/Nimble/Utils/AsyncAwait.swift +++ b/Sources/Nimble/Utils/AsyncAwait.swift @@ -1,5 +1,9 @@ #if !os(WASI) +#if canImport(CoreFoundation) +import CoreFoundation +#endif + import Dispatch import Foundation diff --git a/Sources/Nimble/Utils/AsyncTimerSequence.swift b/Sources/Nimble/Utils/AsyncTimerSequence.swift index dd14b2aef..83c2485f9 100644 --- a/Sources/Nimble/Utils/AsyncTimerSequence.swift +++ b/Sources/Nimble/Utils/AsyncTimerSequence.swift @@ -1,5 +1,8 @@ #if !os(WASI) +#if canImport(CoreFoundation) +import CoreFoundation +#endif import Dispatch import Foundation diff --git a/Sources/Nimble/Utils/PollAwait.swift b/Sources/Nimble/Utils/PollAwait.swift index da23b50ad..1bc1311ba 100644 --- a/Sources/Nimble/Utils/PollAwait.swift +++ b/Sources/Nimble/Utils/PollAwait.swift @@ -1,5 +1,8 @@ #if !os(WASI) +#if canImport(CoreFoundation) +import CoreFoundation +#endif import Dispatch import Foundation @@ -195,24 +198,48 @@ internal class AwaitPromiseBuilder { let timedOutSem = DispatchSemaphore(value: 0) let semTimedOutOrBlocked = DispatchSemaphore(value: 0) semTimedOutOrBlocked.signal() + #if canImport(CoreFoundation) + let runLoop = CFRunLoopGetMain() + #if canImport(Darwin) + let runLoopMode = CFRunLoopMode.defaultMode.rawValue + #else + let runLoopMode = kCFRunLoopDefaultMode + #endif + CFRunLoopPerformBlock(runLoop, runLoopMode) { + if semTimedOutOrBlocked.wait(timeout: .now()) == .success { + timedOutSem.signal() + semTimedOutOrBlocked.signal() + if self.promise.resolveResult(.timedOut) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } + } + // potentially interrupt blocking code on run loop to let timeout code run + CFRunLoopStop(runLoop) + #else let runLoop = RunLoop.main runLoop.perform(inModes: [.default], block: { if semTimedOutOrBlocked.wait(timeout: .now()) == .success { timedOutSem.signal() semTimedOutOrBlocked.signal() if self.promise.resolveResult(.timedOut) { - RunLoop.main.stop() + RunLoop.main._stop() } } }) // potentially interrupt blocking code on run loop to let timeout code run - runLoop.stop() + runLoop._stop() + #endif let now = DispatchTime.now() + forcefullyAbortTimeout.dispatchTimeInterval let didNotTimeOut = timedOutSem.wait(timeout: now) != .success let timeoutWasNotTriggered = semTimedOutOrBlocked.wait(timeout: .now()) == .success if didNotTimeOut && timeoutWasNotTriggered { if self.promise.resolveResult(.blockedRunLoop) { - runLoop.stop() + #if canImport(CoreFoundation) + CFRunLoopStop(CFRunLoopGetMain()) + #else + RunLoop.main._stop() + #endif } } } @@ -300,7 +327,11 @@ internal class Awaiter { if completionCount < 2 { func completeBlock() { if promise.resolveResult(.completed(result)) { - RunLoop.main.stop() + #if canImport(CoreFoundation) + CFRunLoopStop(CFRunLoopGetMain()) + #else + RunLoop.main._stop() + #endif } } @@ -338,12 +369,20 @@ internal class Awaiter { do { if let result = try closure() { if promise.resolveResult(.completed(result)) { - RunLoop.current.stop() + #if canImport(CoreFoundation) + CFRunLoopStop(CFRunLoopGetCurrent()) + #else + RunLoop.current._stop() + #endif } } } catch let error { if promise.resolveResult(.errorThrown(error)) { - RunLoop.current.stop() + #if canImport(CoreFoundation) + CFRunLoopStop(CFRunLoopGetCurrent()) + #else + RunLoop.current._stop() + #endif } } } @@ -377,23 +416,4 @@ internal func pollBlock( return result } -#if canImport(CoreFoundation) -import CoreFoundation - -extension RunLoop { - func stop() { - CFRunLoopStop(getCFRunLoop()) - } -} - -#else - -extension RunLoop { - func stop() { - _stop() - } -} - -#endif - #endif // #if !os(WASI) diff --git a/Tests/NimbleTests/PollingTest+Require.swift b/Tests/NimbleTests/PollingTest+Require.swift index c9518693c..7bdc48464 100644 --- a/Tests/NimbleTests/PollingTest+Require.swift +++ b/Tests/NimbleTests/PollingTest+Require.swift @@ -1,6 +1,9 @@ #if !os(WASI) import Dispatch +#if canImport(CoreFoundation) +import CoreFoundation +#endif import Foundation import XCTest import Nimble From 33c52ffca3906b9fcc045eb92906d0311bab19c0 Mon Sep 17 00:00:00 2001 From: Rachel Brindle Date: Wed, 1 Oct 2025 10:53:03 -0700 Subject: [PATCH 2/2] Re-remove duplicated runloop code --- Sources/Nimble/Utils/AsyncAwait.swift | 3 --- Sources/Nimble/Utils/AsyncTimerSequence.swift | 2 -- Sources/Nimble/Utils/PollAwait.swift | 17 ----------------- Tests/NimbleTests/PollingTest+Require.swift | 4 +--- Tests/NimbleTests/PollingTest.swift | 4 +--- 5 files changed, 2 insertions(+), 28 deletions(-) diff --git a/Sources/Nimble/Utils/AsyncAwait.swift b/Sources/Nimble/Utils/AsyncAwait.swift index 000e84886..e12c5a0d3 100644 --- a/Sources/Nimble/Utils/AsyncAwait.swift +++ b/Sources/Nimble/Utils/AsyncAwait.swift @@ -1,9 +1,6 @@ #if !os(WASI) -#if canImport(CoreFoundation) import CoreFoundation -#endif - import Dispatch import Foundation diff --git a/Sources/Nimble/Utils/AsyncTimerSequence.swift b/Sources/Nimble/Utils/AsyncTimerSequence.swift index 83c2485f9..6bd46b83c 100644 --- a/Sources/Nimble/Utils/AsyncTimerSequence.swift +++ b/Sources/Nimble/Utils/AsyncTimerSequence.swift @@ -1,8 +1,6 @@ #if !os(WASI) -#if canImport(CoreFoundation) import CoreFoundation -#endif import Dispatch import Foundation diff --git a/Sources/Nimble/Utils/PollAwait.swift b/Sources/Nimble/Utils/PollAwait.swift index 1bc1311ba..35758c708 100644 --- a/Sources/Nimble/Utils/PollAwait.swift +++ b/Sources/Nimble/Utils/PollAwait.swift @@ -1,8 +1,6 @@ #if !os(WASI) -#if canImport(CoreFoundation) import CoreFoundation -#endif import Dispatch import Foundation @@ -198,7 +196,6 @@ internal class AwaitPromiseBuilder { let timedOutSem = DispatchSemaphore(value: 0) let semTimedOutOrBlocked = DispatchSemaphore(value: 0) semTimedOutOrBlocked.signal() - #if canImport(CoreFoundation) let runLoop = CFRunLoopGetMain() #if canImport(Darwin) let runLoopMode = CFRunLoopMode.defaultMode.rawValue @@ -216,20 +213,6 @@ internal class AwaitPromiseBuilder { } // potentially interrupt blocking code on run loop to let timeout code run CFRunLoopStop(runLoop) - #else - let runLoop = RunLoop.main - runLoop.perform(inModes: [.default], block: { - if semTimedOutOrBlocked.wait(timeout: .now()) == .success { - timedOutSem.signal() - semTimedOutOrBlocked.signal() - if self.promise.resolveResult(.timedOut) { - RunLoop.main._stop() - } - } - }) - // potentially interrupt blocking code on run loop to let timeout code run - runLoop._stop() - #endif let now = DispatchTime.now() + forcefullyAbortTimeout.dispatchTimeInterval let didNotTimeOut = timedOutSem.wait(timeout: now) != .success let timeoutWasNotTriggered = semTimedOutOrBlocked.wait(timeout: .now()) == .success diff --git a/Tests/NimbleTests/PollingTest+Require.swift b/Tests/NimbleTests/PollingTest+Require.swift index 7bdc48464..2276bc704 100644 --- a/Tests/NimbleTests/PollingTest+Require.swift +++ b/Tests/NimbleTests/PollingTest+Require.swift @@ -1,9 +1,7 @@ #if !os(WASI) -import Dispatch -#if canImport(CoreFoundation) import CoreFoundation -#endif +import Dispatch import Foundation import XCTest import Nimble diff --git a/Tests/NimbleTests/PollingTest.swift b/Tests/NimbleTests/PollingTest.swift index a9d4d72ec..9960eec1d 100644 --- a/Tests/NimbleTests/PollingTest.swift +++ b/Tests/NimbleTests/PollingTest.swift @@ -1,9 +1,7 @@ #if !os(WASI) -import Dispatch -#if canImport(CoreFoundation) import CoreFoundation -#endif +import Dispatch import Foundation import XCTest import Nimble