For my use case I made this restricted clone of Publisher's share() based on escaping continuations. Since documentation explicitely mentions, that the Continuation supports escaping, I believe it's valid. So far it works. Feel free to use and contribute.
extension AsyncStream where Element: Sendable {
func double() -> (AsyncStream<Element>, AsyncStream<Element>) {
var continuation1: AsyncStream<Element>.Continuation!
var continuation2: AsyncStream<Element>.Continuation!
let stream1 = AsyncStream { continuation in
continuation1 = continuation
}
let stream2 = AsyncStream { continuation in
continuation2 = continuation
}
Task {
for await element in self {
continuation1.yield(element)
continuation2.yield(element)
}
continuation1.finish()
continuation2.finish()
}
return (stream1, stream2)
}
}
let integers = ... // as above
let (integers1, integers2) = integers.double()
let evens = integers1.compactMap { i in
i % 2 == 0 ? i : nil
}
let odds = integers2.compactMap { i in
i % 2 == 0 ? nil : i
}
for await e in evens {
print("even:", e)
}
for await o in odds {
print("odd:", o)
}
print("Print over.")
Output
even: 10
even: 8
even: 6
even: 4
even: 2
odd: 9
odd: 7
odd: 5
odd: 3
odd: 1
Print over.