Last active
August 15, 2025 15:00
-
-
Save NikolaiRuhe/de31b999b8c8c58c65e4c2e8724dda74 to your computer and use it in GitHub Desktop.
A property wrapper that creates an AsyncStream yielding values when the property is set.
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 os | |
@propertyWrapper | |
public struct Streaming<Wrapped: Sendable>: Sendable { | |
public var wrappedValue: Wrapped { | |
get { value } | |
set { | |
value = newValue | |
let continuations = protectedContinuations.withLock { $0.values } | |
for continuation in continuations { | |
continuation.yield(newValue) | |
} | |
} | |
} | |
public var projectedValue: Stream { | |
get { | |
let id = nextID | |
let (stream, continuation) = Stream.makeStream(bufferingPolicy: bufferingPolicy) | |
protectedContinuations.withLock { $0[id] = continuation } | |
continuation.onTermination = { [protectedContinuations] _ in | |
protectedContinuations.withLock { $0[id] = nil } | |
} | |
return stream | |
} | |
} | |
public init(wrappedValue: Wrapped, bufferingPolicy: Stream.Continuation.BufferingPolicy = .bufferingNewest(1)) { | |
self.value = wrappedValue | |
self.bufferingPolicy = bufferingPolicy | |
} | |
public typealias Stream = AsyncStream<Wrapped> | |
private var value: Wrapped | |
private let bufferingPolicy: Stream.Continuation.BufferingPolicy | |
private let protectedContinuations: OSAllocatedUnfairLock<[Int: Stream.Continuation]> = .init(initialState: [:]) | |
} | |
fileprivate var nextID: Int { _nextID.withLock { id in defer { id += 1 }; return id } } | |
fileprivate let _nextID: OSAllocatedUnfairLock<Int> = .init(initialState: 42) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage: