Created
February 4, 2025 00:26
-
-
Save darrarski/6ca991841ba9978f58b7d81077f22978 to your computer and use it in GitHub Desktop.
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 ConcurrencyExtras | |
import struct Foundation.UUID | |
@dynamicMemberLookup | |
final class LockIsolatedValueStream<Value>: Sendable where Value: Sendable { | |
init(_ value: Value) { | |
self._lock = LockIsolated(value) | |
} | |
var value: Value { _lock.value } | |
subscript<Subject: Sendable>(dynamicMember keyPath: KeyPath<Value, Subject>) -> Subject { | |
self._lock.value[keyPath: keyPath] | |
} | |
@discardableResult | |
func withValue<T: Sendable>(_ operation: @Sendable (inout Value) throws -> T) rethrows -> T { | |
try _lock.withValue { value in | |
var copy = value | |
defer { | |
value = copy | |
yield(value) | |
} | |
return try operation(©) | |
} | |
} | |
func setValue(_ newValue: @autoclosure @Sendable () throws -> Value) rethrows { | |
try _lock.withValue { value in | |
value = try newValue() | |
yield(value) | |
} | |
} | |
var stream: any AsyncSequence<Value, Never> { | |
AsyncStream { continuation in | |
let id = addContinuation(continuation) | |
continuation.onTermination = { [weak self] _ in | |
self?.removeContinuation(id) | |
} | |
continuation.yield(value) | |
} | |
} | |
private let _lock: LockIsolated<Value> | |
private let _continuations = LockIsolated<[UUID: AsyncStream<Value>.Continuation]>([:]) | |
private func addContinuation(_ continuation: AsyncStream<Value>.Continuation) -> UUID { | |
_continuations.withValue { | |
let id = UUID() | |
$0[id] = continuation | |
return id | |
} | |
} | |
private func removeContinuation(_ id: UUID) { | |
_continuations.withValue { $0[id] = nil } | |
} | |
private func yield(_ value: Value) { | |
_continuations.withValue { [value] continuations in | |
for continuation in continuations.values { | |
continuation.yield(value) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment