Skip to content

Commit 98d4229

Browse files
authored
Add shims and adjust availability to allow for swift 5.6 toolchains to build until source stability is achieved (apple#100)
* Add shims and adjust availability to allow for swift 5.6 toolchains to build until source stability is achieved * Restore availability again
1 parent f9d0911 commit 98d4229

15 files changed

+2247
-23
lines changed

Diff for: Package.swift

+6-13
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,25 @@ let package = Package(
1111
.watchOS("6.0")
1212
],
1313
products: [
14-
.library(
15-
name: "AsyncAlgorithms",
16-
targets: ["AsyncAlgorithms"]),
14+
.library(name: "AsyncAlgorithms", targets: ["AsyncAlgorithms"]),
15+
.library(name: "ClockShims", type: .static, targets: ["ClockShims"]),
1716
.library(name: "AsyncSequenceValidation", targets: ["AsyncSequenceValidation"]),
1817
.library(name: "_CAsyncSequenceValidationSupport", type: .static, targets: ["AsyncSequenceValidation"])
1918
],
2019
dependencies: [],
2120
targets: [
22-
.target(
23-
name: "AsyncAlgorithms"),
21+
.target(name: "AsyncAlgorithms", dependencies: ["ClockShims"]),
22+
.target(name: "ClockShims"),
2423
.target(
2524
name: "AsyncSequenceValidation",
26-
dependencies: ["_CAsyncSequenceValidationSupport"],
27-
swiftSettings: [
28-
.unsafeFlags([
29-
"-Xfrontend", "-enable-experimental-pairwise-build-block"
30-
])
31-
]),
25+
dependencies: ["_CAsyncSequenceValidationSupport", "AsyncAlgorithms"]),
3226
.systemLibrary(name: "_CAsyncSequenceValidationSupport"),
3327
.testTarget(
3428
name: "AsyncAlgorithmsTests",
3529
dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation"],
3630
swiftSettings: [
3731
.unsafeFlags([
38-
"-Xfrontend", "-disable-availability-checking",
39-
"-Xfrontend", "-enable-experimental-pairwise-build-block"
32+
"-Xfrontend", "-disable-availability-checking"
4033
])
4134
]),
4235
]

Diff for: README.md

+8-9
Original file line numberDiff line numberDiff line change
@@ -86,28 +86,27 @@ Finally, add `import AsyncAlgorithms` to your source code.
8686

8787
## Getting Started
8888

89-
⚠️ Please note that this package currently requires a recent [Swift Trunk Development toolchain](https://www.swift.org/download/#trunk-development-main). More information on how to use custom toolchains with Xcode can be viewed [here](https://developer.apple.com/library/archive/documentation/ToolsLanguages/Conceptual/Xcode_Overview/AlternativeToolchains.html).
90-
9189
### Building/Testing Using Xcode on macOS
9290

93-
1. Download the most recent development Xcode toolchain.
94-
2. Install the package
95-
4. Select the development toolchain in Xcode
96-
4. Open the `swift-async-algorithms` package directory in Xcode
97-
5. Build or Test in Xcode as normal
91+
1. Open the `swift-async-algorithms` package directory in Xcode
92+
2. Build or Test in Xcode as normal
93+
94+
### Building/Testing Using Swift Package Manager
9895

99-
⚠️ Note: `swift test` does not currently work properly with custom toolchains for this package.
96+
1. In the `swift-async-algorithms` directory run `swift build` or `swift test` accordingly
10097

10198
### Building/Testing on Linux
10299

103-
1. Download the most recent development toolchain for your Linux distribution
100+
1. Download the most recent toolchain for your Linux distribution
104101
2. Decompress the archive to a path in which the `swift` executable is in the binary search path environment variable (`$PATH`)
105102
3. In the `swift-async-algorithms` directory run `swift build` or `swift test` accordingly
106103

107104
## Source Stability
108105

109106
The Swift Async Algorithms package has a goal of being source stable as soon as possible; version numbers will follow [Semantic Versioning](https://semver.org/). Source breaking changes to public API can only land in a new major version.
110107

108+
Before the version 1.0 the `swift-async-algorithms` package will not be source or ABI stable. Particularly the shims associated with `Clock`, `Instant` and `Duration` are present just to provide backwards compatability to older toolchains. As soon as this is available widely the shims will be removed; which will be an ABI breaking change.
109+
111110
The public API of version 1.0 of the `swift-async-algorithms` package will consist of non-underscored declarations that are marked `public` in the `AsyncAlgorithms` module. Interfaces that aren't part of the public API may continue to change in any release, including patch releases.
112111

113112
Future minor versions of the package may introduce changes to these rules as needed.

Diff for: Sources/AsyncAlgorithms/Reexport.swift

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift Async Algorithms open source project
4+
//
5+
// Copyright (c) 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
@_exported import ClockShims

Diff for: Sources/AsyncSequenceValidation/AsyncSequenceValidationDiagram.swift

+40
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,46 @@ public struct AsyncSequenceValidationDiagram : Sendable {
5656
return Test(inputs: accumulated.inputs, sequence: accumulated.operation, output: Specification(specification: output.component, location: output.location))
5757
}
5858

59+
public static func buildBlock<Operation: AsyncSequence>(_ sequence: Component<Operation>, _ output: Component<String>) -> some AsyncSequenceValidationTest where Operation.Element == String {
60+
let part1 = buildPartialBlock(first: sequence)
61+
let part2 = buildPartialBlock(accumulated: part1, next: output)
62+
return part2
63+
}
64+
65+
public static func buildBlock<Operation: AsyncSequence>(_ input1: Component<String>, _ sequence: Component<Operation>, _ output: Component<String>) -> some AsyncSequenceValidationTest where Operation.Element == String {
66+
let part1 = buildPartialBlock(first: input1)
67+
let part2 = buildPartialBlock(accumulated: part1, next: sequence)
68+
let part3 = buildPartialBlock(accumulated: part2, next: output)
69+
return part3
70+
}
71+
72+
public static func buildBlock<Operation: AsyncSequence>(_ input1: Component<String>, _ input2: Component<String>, _ sequence: Component<Operation>, _ output: Component<String>) -> some AsyncSequenceValidationTest where Operation.Element == String {
73+
let part1 = buildPartialBlock(first: input1)
74+
let part2 = buildPartialBlock(accumulated: part1, next: input2)
75+
let part3 = buildPartialBlock(accumulated: part2, next: sequence)
76+
let part4 = buildPartialBlock(accumulated: part3, next: output)
77+
return part4
78+
}
79+
80+
public static func buildBlock<Operation: AsyncSequence>(_ input1: Component<String>, _ input2: Component<String>, _ input3: Component<String>, _ sequence: Component<Operation>, _ output: Component<String>) -> some AsyncSequenceValidationTest where Operation.Element == String {
81+
let part1 = buildPartialBlock(first: input1)
82+
let part2 = buildPartialBlock(accumulated: part1, next: input2)
83+
let part3 = buildPartialBlock(accumulated: part2, next: input3)
84+
let part4 = buildPartialBlock(accumulated: part3, next: sequence)
85+
let part5 = buildPartialBlock(accumulated: part4, next: output)
86+
return part5
87+
}
88+
89+
public static func buildBlock<Operation: AsyncSequence>(_ input1: Component<String>, _ input2: Component<String>, _ input3: Component<String>, _ input4: Component<String>, _ sequence: Component<Operation>, _ output: Component<String>) -> some AsyncSequenceValidationTest where Operation.Element == String {
90+
let part1 = buildPartialBlock(first: input1)
91+
let part2 = buildPartialBlock(accumulated: part1, next: input2)
92+
let part3 = buildPartialBlock(accumulated: part2, next: input3)
93+
let part4 = buildPartialBlock(accumulated: part3, next: input3)
94+
let part5 = buildPartialBlock(accumulated: part4, next: sequence)
95+
let part6 = buildPartialBlock(accumulated: part5, next: output)
96+
return part6
97+
}
98+
5999
let queue: WorkQueue
60100

61101
public var inputs: InputList

Diff for: Sources/AsyncSequenceValidation/Clock.swift

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12+
import AsyncAlgorithms
13+
1214
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
1315
extension AsyncSequenceValidationDiagram {
1416
public struct Clock {

Diff for: Sources/AsyncSequenceValidation/Test.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//===----------------------------------------------------------------------===//
1111

1212
import _CAsyncSequenceValidationSupport
13+
import AsyncAlgorithms
1314

1415
@_silgen_name("swift_job_run")
1516
@usableFromInline
@@ -33,7 +34,7 @@ extension AsyncSequenceValidationDiagram {
3334
let sequence: Operation
3435
let output: Specification
3536

36-
func test<C: _Concurrency.Clock>(with clock: C, activeTicks: [C.Instant], output: Specification, _ event: (String) -> Void) async throws {
37+
func test<C: ClockShims.Clock>(with clock: C, activeTicks: [C.Instant], output: Specification, _ event: (String) -> Void) async throws {
3738
var iterator = sequence.makeAsyncIterator()
3839
do {
3940
for tick in activeTicks {

Diff for: Sources/ClockShims/Clock.swift

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
import Swift
13+
14+
/// A mechanism in which to measure time, and delay work until a given point
15+
/// in time.
16+
///
17+
/// Types that conform to the `Clock` protocol define a concept of "now" which
18+
/// is the specific instant in time that property is accessed. Any pair of calls
19+
/// to the `now` property may have a minimum duration between them - this
20+
/// minimum resolution is exposed by the `minimumResolution` property to inform
21+
/// any user of the type the expected granularity of accuracy.
22+
///
23+
/// One of the primary uses for clocks is to schedule task sleeping. This method
24+
/// resumes the calling task after a given deadline has been met or passed with
25+
/// a given tolerance value. The tolerance is expected as a leeway around the
26+
/// deadline. The clock may reschedule tasks within the tolerance to ensure
27+
/// efficient execution of resumptions by reducing potential operating system
28+
/// wake-ups. If no tolerance is specified (i.e. nil is passed in) the sleep
29+
/// function is expected to schedule with a default tolerance strategy.
30+
///
31+
/// For more information about specific clocks see `ContinuousClock` and
32+
/// `SuspendingClock`.
33+
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
34+
public protocol Clock: Sendable {
35+
associatedtype Instant: InstantProtocol
36+
37+
var now: Instant { get }
38+
var minimumResolution: Instant.Duration { get }
39+
40+
func sleep(until deadline: Instant, tolerance: Instant.Duration?) async throws
41+
}
42+
43+
44+
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
45+
extension Clock {
46+
/// Measure the elapsed time to execute a closure.
47+
///
48+
/// let clock = ContinuousClock()
49+
/// let elapsed = clock.measure {
50+
/// someWork()
51+
/// }
52+
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
53+
public func measure(_ work: () throws -> Void) rethrows -> Instant.Duration {
54+
let start = now
55+
try work()
56+
let end = now
57+
return start.duration(to: end)
58+
}
59+
60+
/// Measure the elapsed time to execute an asynchronous closure.
61+
///
62+
/// let clock = ContinuousClock()
63+
/// let elapsed = await clock.measure {
64+
/// await someWork()
65+
/// }
66+
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
67+
public func measure(
68+
_ work: () async throws -> Void
69+
) async rethrows -> Instant.Duration {
70+
let start = now
71+
try await work()
72+
let end = now
73+
return start.duration(to: end)
74+
}
75+
}
76+

0 commit comments

Comments
 (0)