swift-nio/Package.swift

148 lines
7.4 KiB
Swift
Raw Normal View History

// swift-tools-version:5.6
2017-04-20 19:13:14 +08:00
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2021 Apple Inc. and the SwiftNIO project authors
2017-04-20 19:13:14 +08:00
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import PackageDescription
let swiftAtomics: PackageDescription.Target.Dependency = .product(name: "Atomics", package: "swift-atomics")
Implement a back-pressure aware `AsyncSequence` source (#2230) * Implement a back-pressure aware `AsyncSequence` source # Motivation We ran into multiple use-cases (https://github.com/apple/swift-nio/pull/2067, https://github.com/grpc/grpc-swift/blob/main/Sources/GRPC/AsyncAwaitSupport/PassthroughMessageSource.swift) already where we want to vend an `AsyncSequence` where elements are produced from the sync world while the consumer is in the async world. Furthermore, we need the `AsyncSequence` to properly support back-pressure. Since we already identified that this is something fundamental for our ecosystem and that current `AsyncSequence` sources are not providing the proper semantics or performance, it would be great to find a single solution that we can use everywhere. Before diving into the code, I think it is good to understand the goals of this `AsyncSequence`: - The `AsyncSequence` should support a single unicast `Subscriber` - The `AsyncSequence` should allow a pluggable back-pressure strategy - The `AsyncSequence` should allow to yield a sequence of elements to avoid aquiring the lock for every element. - We should make sure to do as few thread hops as possible to signal the producer to demand more elements. # Modification This PR introduces a new `AsyncSequence` called `NIOBackPressuredAsyncSequence`. The goal of that sequence to enable sync to async element streaming with back-pressure support. # Result We can now power our sync to async use-cases with this new `AsyncSequence`. # Future work There are couple of things left that I wanna land in a follow up PR: 1. An adaptive back-pressure strategy that grows and shrinks depending on the speed of consumption 2. A throwing version of this sequence 3. Potentially an async version that suspends on `yield()` and resumes when more elements should be demanded. * Fix cancellation handling * Review * Add init helper * Add return types to help the type checker * Fix 5.7 CI * Rename delegate method and update docs * Review * Switch to Deque, rename the type and change the behaviour of yielding an empty sequence * Review comments from George * Review comments by Konrad * Review and add tests for the high low strategy * Fix 5.4 tests * Code review Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-08-04 22:58:28 +08:00
let swiftCollections: PackageDescription.Target.Dependency = .product(name: "DequeModule", package: "swift-collections")
2017-04-20 19:13:14 +08:00
var targets: [PackageDescription.Target] = [
Extract basic data structures to NIOCore. (#1895) Motivation: Currently the "core" NIO module (currently called NIO) contains two fairly distinct kinds of things. The first is the core abstractions and data structures: the things that all NIO programs must necessarily deal with. This includes our base abstraction protocols (e.g. `EventLoop`, `Channel`, and `ChannelHandler`), as well as our base data types (e.g. `ByteBuffer`, `SocketAddress`, `EventLoopFuture`). The second thing the core NIO module contains is the default POSIX sockets event-loop and channels. These are the mainline production loops for NIO programs, and are supported in the various BSD-like OSes to varying extents. These can be thought of as a baseline implementation of the core abstraction protocols that form the first part of NIO. These two fairly distinct use-cases have no particular reason to be glued together, and in fact in gluing them together we have done a bit of a disservice to our adopters. The biggest issue is that it has become impossible to write a NIO program or library that does not bring along the POSIX layer of NIO. This has made porting NIO to other platforms difficult (Windows has been painful, and Webassembly is coming down the road as well), and has also bloated the size of iOS/macOS applications that use NIO via NIOTransportServices, as all of these applications must bring along an event loop and several Channels they will not use. To that end, we plan to begin a scope of work to split the core NIO module in two. Specifically, we intend to extract the baseline protocols and data types into a new module, called `NIOCore`, which will be able to be the baseline NIO module. The end goal is that libraries that implement protocols on top of SwiftNIO should be able to depend solely on `NIOCore`, not `NIO`. This will allow NIO applications to bring along only the event loops they want or need, without needing to pay for the POSIX sockets implementation. This should also make porting easier, as there will be no pressure to bring the existing `NIO` module to new platforms if it does not fit well. Modifications: This is the first in a series of patches, which extracts some of the low-hanging fruit. In particular, it extracts: - `ByteBuffer` (and associated types) - `RecvByteBufferAllocator` - `CircularBuffer` This also adds in the backwards compatibility shim: the `NIO` package performs an exported import of `NIOCore`. This will allow this change to avoid breaking API. However, to make a clean break we intend not to release a new NIO minor version until we have completed our extraction. If we fail to do this it won't be the end of the world, we can release subsequent minor versions that continue to extract new types. However, as much as possible should go at once. This patch also duplicates a few methods and files. At the end of the patch series we need to reconcile this duplication. In many cases the duplication will no longer be necessary, but in some cases we may have necessary duplicates. Result: The first step along the road to better platform citizenship is taken.
2021-07-14 16:58:25 +08:00
.target(name: "NIOCore",
Implement a `NIOAsyncWriter` (#2251) * Implement a `NIOAsyncWriter` # Motivation We previously added the `NIOAsyncProducer` to bridge between the NIO channel pipeline and the asynchronous world. However, we still need something to bridge writes from the asynchronous world back to the NIO channel pipeline. # Modification This PR adds a new `NIOAsyncWriter` type that allows us to asynchronously `yield` elements to it. On the other side, we can register a `NIOAsyncWriterDelegate` which will get informed about any written elements. Furthermore, the synchronous side can toggle the writability of the `AsyncWriter` which allows it to implement flow control. A main goal of this type is to be as performant as possible. To achieve this I did the following things: - Make everything generic and inlinable - Use a class with a lock instead of an actor - Provide methods to yield a sequence of things which allows users to reduce the amount of times the lock gets acquired. # Result We now have the means to bridge writes from the asynchronous world to the synchronous * Remove the completion struct and incorporate code review comments * Fixup some refactoring leftovers * More code review comments * Move to holding the lock around the delegate and moved the delegate into the state machine * Comment fixups * More doc fixes * Call finish when the sink deinits * Refactor the writer to only yield Deques and rename the delegate to NIOAsyncWriterSinkDelegate * Review * Fix some warnings * Fix benchmark sendability * Remove Failure generic parameter and allow sending of an error through the Sink
2022-09-21 17:53:53 +08:00
dependencies: ["NIOConcurrencyHelpers", "CNIOLinux", "CNIOWindows", swiftCollections, swiftAtomics]),
.target(name: "_NIODataStructures"),
.target(name: "NIOEmbedded",
dependencies: ["NIOCore",
"NIOConcurrencyHelpers",
"_NIODataStructures",
swiftAtomics,
swiftCollections]),
.target(name: "NIOPosix",
2017-04-20 19:13:14 +08:00
dependencies: ["CNIOLinux",
"CNIODarwin",
"CNIOWindows",
Extract basic data structures to NIOCore. (#1895) Motivation: Currently the "core" NIO module (currently called NIO) contains two fairly distinct kinds of things. The first is the core abstractions and data structures: the things that all NIO programs must necessarily deal with. This includes our base abstraction protocols (e.g. `EventLoop`, `Channel`, and `ChannelHandler`), as well as our base data types (e.g. `ByteBuffer`, `SocketAddress`, `EventLoopFuture`). The second thing the core NIO module contains is the default POSIX sockets event-loop and channels. These are the mainline production loops for NIO programs, and are supported in the various BSD-like OSes to varying extents. These can be thought of as a baseline implementation of the core abstraction protocols that form the first part of NIO. These two fairly distinct use-cases have no particular reason to be glued together, and in fact in gluing them together we have done a bit of a disservice to our adopters. The biggest issue is that it has become impossible to write a NIO program or library that does not bring along the POSIX layer of NIO. This has made porting NIO to other platforms difficult (Windows has been painful, and Webassembly is coming down the road as well), and has also bloated the size of iOS/macOS applications that use NIO via NIOTransportServices, as all of these applications must bring along an event loop and several Channels they will not use. To that end, we plan to begin a scope of work to split the core NIO module in two. Specifically, we intend to extract the baseline protocols and data types into a new module, called `NIOCore`, which will be able to be the baseline NIO module. The end goal is that libraries that implement protocols on top of SwiftNIO should be able to depend solely on `NIOCore`, not `NIO`. This will allow NIO applications to bring along only the event loops they want or need, without needing to pay for the POSIX sockets implementation. This should also make porting easier, as there will be no pressure to bring the existing `NIO` module to new platforms if it does not fit well. Modifications: This is the first in a series of patches, which extracts some of the low-hanging fruit. In particular, it extracts: - `ByteBuffer` (and associated types) - `RecvByteBufferAllocator` - `CircularBuffer` This also adds in the backwards compatibility shim: the `NIO` package performs an exported import of `NIOCore`. This will allow this change to avoid breaking API. However, to make a clean break we intend not to release a new NIO minor version until we have completed our extraction. If we fail to do this it won't be the end of the world, we can release subsequent minor versions that continue to extract new types. However, as much as possible should go at once. This patch also duplicates a few methods and files. At the end of the patch series we need to reconcile this duplication. In many cases the duplication will no longer be necessary, but in some cases we may have necessary duplicates. Result: The first step along the road to better platform citizenship is taken.
2021-07-14 16:58:25 +08:00
"NIOConcurrencyHelpers",
"NIOCore",
"_NIODataStructures",
swiftAtomics]),
.target(name: "NIO",
dependencies: ["NIOCore",
"NIOEmbedded",
"NIOPosix"]),
.target(name: "_NIOConcurrency",
dependencies: ["NIO", "NIOCore"]),
.target(name: "NIOFoundationCompat", dependencies: ["NIO", "NIOCore"]),
.target(name: "CNIOAtomics", dependencies: []),
.target(name: "CNIOSHA1", dependencies: []),
2017-04-20 19:13:14 +08:00
.target(name: "CNIOLinux", dependencies: []),
.target(name: "CNIODarwin", dependencies: [], cSettings: [.define("__APPLE_USE_RFC_3542")]),
.target(name: "CNIOWindows", dependencies: []),
2017-04-20 19:13:14 +08:00
.target(name: "NIOConcurrencyHelpers",
dependencies: ["CNIOAtomics"]),
.target(name: "NIOHTTP1",
dependencies: ["NIO", "NIOCore", "NIOConcurrencyHelpers", "CNIOLLHTTP"]),
.executableTarget(name: "NIOEchoServer",
dependencies: ["NIOPosix", "NIOCore", "NIOConcurrencyHelpers"],
exclude: ["README.md"]),
.executableTarget(name: "NIOEchoClient",
dependencies: ["NIOPosix", "NIOCore", "NIOConcurrencyHelpers"],
exclude: ["README.md"]),
.executableTarget(name: "NIOHTTP1Server",
dependencies: ["NIOPosix", "NIOCore", "NIOHTTP1", "NIOConcurrencyHelpers"],
exclude: ["README.md"]),
.executableTarget(name: "NIOHTTP1Client",
dependencies: ["NIOPosix", "NIOCore", "NIOHTTP1", "NIOConcurrencyHelpers"],
exclude: ["README.md"]),
.target(
name: "CNIOLLHTTP",
cSettings: [.define("LLHTTP_STRICT_MODE")]
),
.target(name: "NIOTLS", dependencies: ["NIO", "NIOCore"]),
.executableTarget(name: "NIOChatServer",
dependencies: ["NIOPosix", "NIOCore", "NIOConcurrencyHelpers"],
exclude: ["README.md"]),
.executableTarget(name: "NIOChatClient",
dependencies: ["NIOPosix", "NIOCore", "NIOConcurrencyHelpers"],
exclude: ["README.md"]),
.target(name: "NIOWebSocket",
dependencies: ["NIO", "NIOCore", "NIOHTTP1", "CNIOSHA1"]),
.executableTarget(name: "NIOWebSocketServer",
dependencies: ["NIOPosix", "NIOCore", "NIOHTTP1", "NIOWebSocket"],
exclude: ["README.md"]),
.executableTarget(name: "NIOWebSocketClient",
dependencies: ["NIOPosix", "NIOCore", "NIOHTTP1", "NIOWebSocket"],
exclude: ["README.md"]),
.executableTarget(name: "NIOPerformanceTester",
dependencies: ["NIOPosix", "NIOCore", "NIOEmbedded", "NIOHTTP1", "NIOFoundationCompat", "NIOWebSocket"]),
.executableTarget(name: "NIOMulticastChat",
dependencies: ["NIOPosix", "NIOCore"]),
.executableTarget(name: "NIOUDPEchoServer",
dependencies: ["NIOPosix", "NIOCore"],
exclude: ["README.md"]),
.executableTarget(name: "NIOUDPEchoClient",
dependencies: ["NIOPosix", "NIOCore"],
exclude: ["README.md"]),
.target(name: "NIOTestUtils",
dependencies: ["NIOPosix", "NIOCore", "NIOEmbedded", "NIOHTTP1", swiftAtomics]),
.executableTarget(name: "NIOCrashTester",
dependencies: ["NIOPosix", "NIOCore", "NIOEmbedded", "NIOHTTP1", "NIOWebSocket", "NIOFoundationCompat"]),
.executableTarget(name: "NIOAsyncAwaitDemo",
dependencies: ["NIOPosix", "NIOCore", "NIOHTTP1"]),
.testTarget(name: "NIOCoreTests",
dependencies: ["NIOCore", "NIOEmbedded", "NIOFoundationCompat"]),
.testTarget(name: "NIOEmbeddedTests",
dependencies: ["NIOConcurrencyHelpers", "NIOCore", "NIOEmbedded"]),
.testTarget(name: "NIOPosixTests",
dependencies: ["NIOPosix", "NIOCore", "NIOFoundationCompat", "NIOTestUtils", "NIOConcurrencyHelpers", "NIOEmbedded", "CNIOLinux"]),
2017-04-20 19:13:14 +08:00
.testTarget(name: "NIOConcurrencyHelpersTests",
dependencies: ["NIOConcurrencyHelpers", "NIOCore"]),
.testTarget(name: "NIODataStructuresTests",
dependencies: ["_NIODataStructures"]),
2017-04-20 19:13:14 +08:00
.testTarget(name: "NIOHTTP1Tests",
dependencies: ["NIOCore", "NIOEmbedded", "NIOPosix", "NIOHTTP1", "NIOFoundationCompat", "NIOTestUtils"]),
2017-04-20 19:13:14 +08:00
.testTarget(name: "NIOTLSTests",
dependencies: ["NIOCore", "NIOEmbedded", "NIOTLS", "NIOFoundationCompat"]),
.testTarget(name: "NIOWebSocketTests",
dependencies: ["NIOCore", "NIOEmbedded", "NIOWebSocket"]),
.testTarget(name: "NIOTestUtilsTests",
dependencies: ["NIOTestUtils", "NIOCore", "NIOEmbedded", "NIOPosix"]),
.testTarget(name: "NIOFoundationCompatTests",
dependencies: ["NIOCore", "NIOFoundationCompat"]),
.testTarget(name: "NIOTests",
dependencies: ["NIO"]),
2017-04-20 19:13:14 +08:00
]
let package = Package(
name: "swift-nio",
products: [
Extract basic data structures to NIOCore. (#1895) Motivation: Currently the "core" NIO module (currently called NIO) contains two fairly distinct kinds of things. The first is the core abstractions and data structures: the things that all NIO programs must necessarily deal with. This includes our base abstraction protocols (e.g. `EventLoop`, `Channel`, and `ChannelHandler`), as well as our base data types (e.g. `ByteBuffer`, `SocketAddress`, `EventLoopFuture`). The second thing the core NIO module contains is the default POSIX sockets event-loop and channels. These are the mainline production loops for NIO programs, and are supported in the various BSD-like OSes to varying extents. These can be thought of as a baseline implementation of the core abstraction protocols that form the first part of NIO. These two fairly distinct use-cases have no particular reason to be glued together, and in fact in gluing them together we have done a bit of a disservice to our adopters. The biggest issue is that it has become impossible to write a NIO program or library that does not bring along the POSIX layer of NIO. This has made porting NIO to other platforms difficult (Windows has been painful, and Webassembly is coming down the road as well), and has also bloated the size of iOS/macOS applications that use NIO via NIOTransportServices, as all of these applications must bring along an event loop and several Channels they will not use. To that end, we plan to begin a scope of work to split the core NIO module in two. Specifically, we intend to extract the baseline protocols and data types into a new module, called `NIOCore`, which will be able to be the baseline NIO module. The end goal is that libraries that implement protocols on top of SwiftNIO should be able to depend solely on `NIOCore`, not `NIO`. This will allow NIO applications to bring along only the event loops they want or need, without needing to pay for the POSIX sockets implementation. This should also make porting easier, as there will be no pressure to bring the existing `NIO` module to new platforms if it does not fit well. Modifications: This is the first in a series of patches, which extracts some of the low-hanging fruit. In particular, it extracts: - `ByteBuffer` (and associated types) - `RecvByteBufferAllocator` - `CircularBuffer` This also adds in the backwards compatibility shim: the `NIO` package performs an exported import of `NIOCore`. This will allow this change to avoid breaking API. However, to make a clean break we intend not to release a new NIO minor version until we have completed our extraction. If we fail to do this it won't be the end of the world, we can release subsequent minor versions that continue to extract new types. However, as much as possible should go at once. This patch also duplicates a few methods and files. At the end of the patch series we need to reconcile this duplication. In many cases the duplication will no longer be necessary, but in some cases we may have necessary duplicates. Result: The first step along the road to better platform citizenship is taken.
2021-07-14 16:58:25 +08:00
.library(name: "NIOCore", targets: ["NIOCore"]),
2017-04-20 19:13:14 +08:00
.library(name: "NIO", targets: ["NIO"]),
.library(name: "NIOEmbedded", targets: ["NIOEmbedded"]),
.library(name: "NIOPosix", targets: ["NIOPosix"]),
.library(name: "_NIOConcurrency", targets: ["_NIOConcurrency"]),
2017-04-20 19:13:14 +08:00
.library(name: "NIOTLS", targets: ["NIOTLS"]),
.library(name: "NIOHTTP1", targets: ["NIOHTTP1"]),
.library(name: "NIOConcurrencyHelpers", targets: ["NIOConcurrencyHelpers"]),
.library(name: "NIOFoundationCompat", targets: ["NIOFoundationCompat"]),
.library(name: "NIOWebSocket", targets: ["NIOWebSocket"]),
.library(name: "NIOTestUtils", targets: ["NIOTestUtils"]),
2017-04-20 19:13:14 +08:00
],
dependencies: [
.package(url: "https://github.com/apple/swift-atomics.git", from: "1.0.2"),
Implement a back-pressure aware `AsyncSequence` source (#2230) * Implement a back-pressure aware `AsyncSequence` source # Motivation We ran into multiple use-cases (https://github.com/apple/swift-nio/pull/2067, https://github.com/grpc/grpc-swift/blob/main/Sources/GRPC/AsyncAwaitSupport/PassthroughMessageSource.swift) already where we want to vend an `AsyncSequence` where elements are produced from the sync world while the consumer is in the async world. Furthermore, we need the `AsyncSequence` to properly support back-pressure. Since we already identified that this is something fundamental for our ecosystem and that current `AsyncSequence` sources are not providing the proper semantics or performance, it would be great to find a single solution that we can use everywhere. Before diving into the code, I think it is good to understand the goals of this `AsyncSequence`: - The `AsyncSequence` should support a single unicast `Subscriber` - The `AsyncSequence` should allow a pluggable back-pressure strategy - The `AsyncSequence` should allow to yield a sequence of elements to avoid aquiring the lock for every element. - We should make sure to do as few thread hops as possible to signal the producer to demand more elements. # Modification This PR introduces a new `AsyncSequence` called `NIOBackPressuredAsyncSequence`. The goal of that sequence to enable sync to async element streaming with back-pressure support. # Result We can now power our sync to async use-cases with this new `AsyncSequence`. # Future work There are couple of things left that I wanna land in a follow up PR: 1. An adaptive back-pressure strategy that grows and shrinks depending on the speed of consumption 2. A throwing version of this sequence 3. Potentially an async version that suspends on `yield()` and resumes when more elements should be demanded. * Fix cancellation handling * Review * Add init helper * Add return types to help the type checker * Fix 5.7 CI * Rename delegate method and update docs * Review * Switch to Deque, rename the type and change the behaviour of yielding an empty sequence * Review comments from George * Review comments by Konrad * Review and add tests for the high low strategy * Fix 5.4 tests * Code review Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-08-04 22:58:28 +08:00
.package(url: "https://github.com/apple/swift-collections.git", from: "1.0.2"),
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"),
2017-04-20 19:13:14 +08:00
],
targets: targets
)