Skip to content

Commit f429665

Browse files
committed
Got the combineLatestMany algorithm working, using Swift 6.2+
1 parent 5a4946b commit f429665

File tree

4 files changed

+36
-23
lines changed

4 files changed

+36
-23
lines changed

Sources/AsyncAlgorithms/CombineLatest/AsyncCombineLatestManySequence.swift

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12+
#if compiler(>=6.2)
13+
1214
/// Creates an asynchronous sequence that combines the latest values from many `AsyncSequence` types
1315
/// by emitting a tuple of the values. ``combineLatestMany(_:)`` only emits a value whenever any of the base `AsyncSequence`s
1416
/// emit a value (so long as each of the bases have emitted at least one value).
@@ -58,13 +60,12 @@ public struct AsyncCombineLatestManySequence<Element: Sendable, Failure: Error>:
5860
}
5961

6062
func next() async throws(Failure) -> [Element]? {
61-
fatalError()
62-
// guard let element = try await self.storage.next() else {
63-
// return nil
64-
// }
65-
//
66-
// // This force unwrap is safe since there must be a third element.
67-
// return element
63+
guard let element = try await self.storage.next() else {
64+
return nil
65+
}
66+
67+
// This force unwrap is safe since there must be a third element.
68+
return element
6869
}
6970
}
7071

@@ -82,3 +83,5 @@ public struct AsyncCombineLatestManySequence<Element: Sendable, Failure: Error>:
8283

8384
@available(*, unavailable)
8485
extension AsyncCombineLatestManySequence.Iterator: Sendable {}
86+
87+
#endif

Sources/AsyncAlgorithms/CombineLatest/CombineLatestManyStateMachine.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12+
#if compiler(>=6.2)
13+
1214
import DequeModule
1315

1416
/// State machine for combine latest
@@ -595,3 +597,5 @@ struct CombineLatestManyStateMachine<Element: Sendable, Failure: Error>: Sendabl
595597
}
596598
}
597599
}
600+
601+
#endif

Sources/AsyncAlgorithms/CombineLatest/CombineLatestManyStorage.swift

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12+
#if compiler(>=6.2)
13+
1214
@available(AsyncAlgorithms 1.1, *)
1315
final class CombineLatestManyStorage<Element: Sendable, Failure: Error>: Sendable {
1416
typealias StateMachine = CombineLatestManyStateMachine<Element, Failure>
@@ -35,9 +37,9 @@ final class CombineLatestManyStorage<Element: Sendable, Failure: Error>: Sendabl
3537
}
3638
}
3739

38-
func next() async throws -> [Element]? {
39-
try await withTaskCancellationHandler {
40-
let result = await withUnsafeContinuation { continuation in
40+
func next() async throws(Failure) -> [Element]? {
41+
let result = await withTaskCancellationHandler {
42+
await withUnsafeContinuation { continuation in
4143
let action: StateMachine.NextAction? = self.stateMachine.withCriticalRegion { stateMachine in
4244
let action = stateMachine.next(for: continuation)
4345
switch action {
@@ -82,9 +84,6 @@ final class CombineLatestManyStorage<Element: Sendable, Failure: Error>: Sendabl
8284
break
8385
}
8486
}
85-
86-
return try result._rethrowGet()
87-
8887
} onCancel: {
8988
let action = self.stateMachine.withCriticalRegion { stateMachine in
9089
stateMachine.cancelled()
@@ -96,19 +95,20 @@ final class CombineLatestManyStorage<Element: Sendable, Failure: Error>: Sendabl
9695
let task,
9796
let upstreamContinuations
9897
):
99-
task.cancel()
98+
task.cancel()
10099
upstreamContinuations.forEach { $0.resume() }
101100

102101
downstreamContinuation.resume(returning: .success(nil))
103102

104103
case .cancelTaskAndUpstreamContinuations(let task, let upstreamContinuations):
105-
task.cancel()
104+
task.cancel()
106105
upstreamContinuations.forEach { $0.resume() }
107106

108107
case .none:
109108
break
110109
}
111110
}
111+
return try result.get()
112112
}
113113

114114
private func startTask(
@@ -234,3 +234,5 @@ final class CombineLatestManyStorage<Element: Sendable, Failure: Error>: Sendabl
234234
stateMachine.taskIsStarted(task: task, downstreamContinuation: downstreamContinuation)
235235
}
236236
}
237+
238+
#endif

Tests/AsyncAlgorithmsTests/TestCombineLatestMany.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12+
#if compiler(>=6.2)
13+
1214
import XCTest
1315
import AsyncAlgorithms
1416

@@ -46,40 +48,42 @@ final class TestCombineLatestMany: XCTestCase {
4648
c.advance()
4749

4850
value = await validator.validate()
49-
XCTAssertEqual(value, [(1, "a", 4)])
51+
XCTAssertEqual(value, [[1, 4, 7]])
5052
a.advance()
5153

5254
value = await validator.validate()
53-
XCTAssertEqual(value, [(1, "a", 4), (2, "a", 4)])
55+
XCTAssertEqual(value, [[1, 4, 7], [2, 4, 7]])
5456
b.advance()
5557

5658
value = await validator.validate()
57-
XCTAssertEqual(value, [(1, "a", 4), (2, "a", 4), (2, "b", 4)])
59+
XCTAssertEqual(value, [[1, 4, 7], [2, 4, 7], [2, 5, 7]])
5860
c.advance()
5961

6062
value = await validator.validate()
61-
XCTAssertEqual(value, [(1, "a", 4), (2, "a", 4), (2, "b", 4), (2, "b", 5)])
63+
XCTAssertEqual(value, [[1, 4, 7], [2, 4, 7], [2, 5, 7], [2, 5, 8]])
6264
a.advance()
6365

6466
value = await validator.validate()
65-
XCTAssertEqual(value, [(1, "a", 4), (2, "a", 4), (2, "b", 4), (2, "b", 5), (3, "b", 5)])
67+
XCTAssertEqual(value, [[1, 4, 7], [2, 4, 7], [2, 5, 7], [2, 5, 8], [3, 5, 8]])
6668
b.advance()
6769

6870
value = await validator.validate()
69-
XCTAssertEqual(value, [(1, "a", 4), (2, "a", 4), (2, "b", 4), (2, "b", 5), (3, "b", 5), (3, "c", 5)])
71+
XCTAssertEqual(value, [[1, 4, 7], [2, 4, 7], [2, 5, 7], [2, 5, 8], [3, 5, 8], [3, 6, 8]])
7072
c.advance()
7173

7274
value = await validator.validate()
7375
XCTAssertEqual(
7476
value,
75-
[(1, "a", 4), (2, "a", 4), (2, "b", 4), (2, "b", 5), (3, "b", 5), (3, "c", 5), (3, "c", 6)]
77+
[[1, 4, 7], [2, 4, 7], [2, 5, 7], [2, 5, 8], [3, 5, 8], [3, 6, 8], [3, 6, 9]]
7678
)
7779

7880
await fulfillment(of: [finished], timeout: 1.0)
7981
value = validator.current
8082
XCTAssertEqual(
8183
value,
82-
[(1, "a", 4), (2, "a", 4), (2, "b", 4), (2, "b", 5), (3, "b", 5), (3, "c", 5), (3, "c", 6)]
84+
[[1, 4, 7], [2, 4, 7], [2, 5, 7], [2, 5, 8], [3, 5, 8], [3, 6, 8], [3, 6, 9]]
8385
)
8486
}
8587
}
88+
89+
#endif

0 commit comments

Comments
 (0)