Skip to content

Commit 1b6b715

Browse files
fix: crash on <ios 18
1 parent 7d7ee6f commit 1b6b715

File tree

1 file changed

+36
-37
lines changed

1 file changed

+36
-37
lines changed

Sources/AsyncAlgorithms/AsyncShareSequence.swift

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -590,45 +590,44 @@ where Base.Element: Sendable, Base: _SendableMetatype, Base.AsyncIterator: _Send
590590
}
591591

592592
func next(isolation actor: isolated (any Actor)?, id: Int) async throws -> Base.Element? {
593-
let (factory, cancelled) = state.withLock { state -> ((@Sendable () -> sending Base.AsyncIterator)?, Bool) in
594-
switch state.iteratingTask {
595-
case .pending(let factory):
596-
state.iteratingTask = .starting
597-
return (factory, false)
598-
case .cancelled:
599-
return (nil, true)
600-
default:
601-
return (nil, false)
602-
}
603-
}
604-
if cancelled { return nil }
605-
if let factory {
606-
let task: Task<Void, Never>
607-
// for the fancy dance of availability and canImport see the comment on the next check for details
608-
#if swift(>=6.2)
609-
if #available(macOS 26.0, iOS 26.0, tvOS 26.0, visionOS 26.0, *) {
610-
task = Task(name: "Share Iteration") { [factory, self] in
611-
await iterationLoop(factory: factory)
612-
}
613-
} else {
614-
task = Task.detached(name: "Share Iteration") { [factory, self] in
615-
await iterationLoop(factory: factory)
593+
let iteratingTask = state.withLock { state -> IteratingTask in
594+
defer {
595+
if case .pending = state.iteratingTask {
596+
state.iteratingTask = .starting
597+
}
616598
}
599+
return state.iteratingTask
617600
}
618-
#else
619-
task = Task.detached { [factory, self] in
620-
await iterationLoop(factory: factory)
621-
}
622-
#endif
623-
// Known Issue: there is a very small race where the task may not get a priority escalation during startup
624-
// this unfortuantely cannot be avoided since the task should ideally not be formed within the critical
625-
// region of the state. Since that could lead to potential deadlocks in low-core-count systems.
626-
// That window is relatively small and can be revisited if a suitable proof of safe behavior can be
627-
// determined.
628-
state.withLock { state in
629-
precondition(state.iteratingTask.isStarting)
630-
state.iteratingTask = .running(task)
631-
}
601+
602+
if case .cancelled = iteratingTask { return nil }
603+
604+
if case .pending(let factory) = iteratingTask {
605+
let task: Task<Void, Never>
606+
// for the fancy dance of availability and canImport see the comment on the next check for details
607+
#if swift(>=6.2)
608+
if #available(macOS 26.0, iOS 26.0, tvOS 26.0, visionOS 26.0, *) {
609+
task = Task(name: "Share Iteration") { [factory, self] in
610+
await iterationLoop(factory: factory)
611+
}
612+
} else {
613+
task = Task.detached(name: "Share Iteration") { [factory, self] in
614+
await iterationLoop(factory: factory)
615+
}
616+
}
617+
#else
618+
task = Task.detached { [factory, self] in
619+
await iterationLoop(factory: factory)
620+
}
621+
#endif
622+
// Known Issue: there is a very small race where the task may not get a priority escalation during startup
623+
// this unfortuantely cannot be avoided since the task should ideally not be formed within the critical
624+
// region of the state. Since that could lead to potential deadlocks in low-core-count systems.
625+
// That window is relatively small and can be revisited if a suitable proof of safe behavior can be
626+
// determined.
627+
state.withLock { state in
628+
precondition(state.iteratingTask.isStarting)
629+
state.iteratingTask = .running(task)
630+
}
632631
}
633632

634633
// withTaskPriorityEscalationHandler is only available for the '26 releases and the 6.2 version of

0 commit comments

Comments
 (0)