diff --git a/Package.swift b/Package.swift index a1562d76..56417e84 100644 --- a/Package.swift +++ b/Package.swift @@ -16,7 +16,7 @@ let package = Package( .library(name: "_CAsyncSequenceValidationSupport", type: .static, targets: ["AsyncSequenceValidation"]), .library(name: "AsyncAlgorithms_XCTest", targets: ["AsyncAlgorithms_XCTest"]), ], - dependencies: [.package(url: "https://github.com/apple/swift-collections.git", .upToNextMajor(from: "1.0.3"))], + dependencies: [.package(url: "https://github.com/apple/swift-collections.git", .upToNextMajor(from: "1.0.4"))], targets: [ .target( name: "AsyncAlgorithms", diff --git a/Sources/AsyncAlgorithms/Buffer/BoundedBufferStateMachine.swift b/Sources/AsyncAlgorithms/Buffer/BoundedBufferStateMachine.swift index a5c50a61..b863bc50 100644 --- a/Sources/AsyncAlgorithms/Buffer/BoundedBufferStateMachine.swift +++ b/Sources/AsyncAlgorithms/Buffer/BoundedBufferStateMachine.swift @@ -16,7 +16,7 @@ struct BoundedBufferStateMachine { typealias SuspendedProducer = UnsafeContinuation typealias SuspendedConsumer = UnsafeContinuation?, Never> - private enum State { + fileprivate enum State { case initial(base: Base) case buffering( task: Task, @@ -308,3 +308,6 @@ struct BoundedBufferStateMachine { } } } + +extension BoundedBufferStateMachine: Sendable where Base: Sendable { } +extension BoundedBufferStateMachine.State: Sendable where Base: Sendable { } diff --git a/Sources/AsyncAlgorithms/Buffer/UnboundedBufferStateMachine.swift b/Sources/AsyncAlgorithms/Buffer/UnboundedBufferStateMachine.swift index b163619a..a43c2023 100644 --- a/Sources/AsyncAlgorithms/Buffer/UnboundedBufferStateMachine.swift +++ b/Sources/AsyncAlgorithms/Buffer/UnboundedBufferStateMachine.swift @@ -21,7 +21,7 @@ struct UnboundedBufferStateMachine { case bufferingOldest(Int) } - private enum State { + fileprivate enum State { case initial(base: Base) case buffering( task: Task, @@ -248,3 +248,6 @@ struct UnboundedBufferStateMachine { } } } + +extension UnboundedBufferStateMachine: Sendable where Base: Sendable { } +extension UnboundedBufferStateMachine.State: Sendable where Base: Sendable { } diff --git a/Sources/AsyncAlgorithms/Channels/AsyncChannel.swift b/Sources/AsyncAlgorithms/Channels/AsyncChannel.swift index 75becf2d..8035d06a 100644 --- a/Sources/AsyncAlgorithms/Channels/AsyncChannel.swift +++ b/Sources/AsyncAlgorithms/Channels/AsyncChannel.swift @@ -19,7 +19,7 @@ /// on the `Iterator` is made, or when `finish()` is called from another Task. /// As `finish()` induces a terminal state, there is no more need for a back pressure management. /// This function does not suspend and will finish all the pending iterations. -public final class AsyncChannel: AsyncSequence, @unchecked Sendable { +public final class AsyncChannel: AsyncSequence, @unchecked Sendable { public typealias Element = Element public typealias AsyncIterator = Iterator diff --git a/Sources/AsyncAlgorithms/Channels/AsyncThrowingChannel.swift b/Sources/AsyncAlgorithms/Channels/AsyncThrowingChannel.swift index 28de36ae..2fc48dfe 100644 --- a/Sources/AsyncAlgorithms/Channels/AsyncThrowingChannel.swift +++ b/Sources/AsyncAlgorithms/Channels/AsyncThrowingChannel.swift @@ -18,7 +18,7 @@ /// and is resumed when the next call to `next()` on the `Iterator` is made, or when `finish()`/`fail(_:)` is called /// from another Task. As `finish()` and `fail(_:)` induce a terminal state, there is no more need for a back pressure management. /// Those functions do not suspend and will finish all the pending iterations. -public final class AsyncThrowingChannel: AsyncSequence, @unchecked Sendable { +public final class AsyncThrowingChannel: AsyncSequence, @unchecked Sendable { public typealias Element = Element public typealias AsyncIterator = Iterator diff --git a/Sources/AsyncAlgorithms/Channels/ChannelStateMachine.swift b/Sources/AsyncAlgorithms/Channels/ChannelStateMachine.swift index 2972c754..e823e5f7 100644 --- a/Sources/AsyncAlgorithms/Channels/ChannelStateMachine.swift +++ b/Sources/AsyncAlgorithms/Channels/ChannelStateMachine.swift @@ -10,8 +10,11 @@ //===----------------------------------------------------------------------===// @_implementationOnly import OrderedCollections -struct ChannelStateMachine: Sendable { - private struct SuspendedProducer: Hashable { +// NOTE: this is only marked as unchecked since the swift-collections tag is before auditing for Sendable +extension OrderedSet: @unchecked Sendable where Element: Sendable { } + +struct ChannelStateMachine: Sendable { + private struct SuspendedProducer: Hashable, Sendable { let id: UInt64 let continuation: UnsafeContinuation? let element: Element? @@ -29,7 +32,7 @@ struct ChannelStateMachine: Sendable { } } - private struct SuspendedConsumer: Hashable { + private struct SuspendedConsumer: Hashable, Sendable { let id: UInt64 let continuation: UnsafeContinuation? @@ -51,7 +54,7 @@ struct ChannelStateMachine: Sendable { case failed(Error) } - private enum State { + private enum State: Sendable { case channeling( suspendedProducers: OrderedSet, cancelledProducers: Set, diff --git a/Sources/AsyncAlgorithms/Channels/ChannelStorage.swift b/Sources/AsyncAlgorithms/Channels/ChannelStorage.swift index da398dbc..12b5ba72 100644 --- a/Sources/AsyncAlgorithms/Channels/ChannelStorage.swift +++ b/Sources/AsyncAlgorithms/Channels/ChannelStorage.swift @@ -8,7 +8,7 @@ // See https://swift.org/LICENSE.txt for license information // //===----------------------------------------------------------------------===// -struct ChannelStorage: Sendable { +struct ChannelStorage: Sendable { private let stateMachine: ManagedCriticalState> private let ids = ManagedCriticalState(0)