Skip to content

Commit 52b1f3d

Browse files
Merge pull request #21 from ZirgVoice/concurrency
Concurrency
2 parents c6129d9 + 0af209a commit 52b1f3d

File tree

11 files changed

+1218
-19
lines changed

11 files changed

+1218
-19
lines changed

.github/workflows/build.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ jobs:
6161
runs-on: ubuntu-22.04
6262
strategy:
6363
matrix:
64-
swift: ["5.7", "5.8", "5.9", "5.10"]
64+
swift: ["5.9", "5.10"]
6565
steps:
6666
- uses: swift-actions/setup-swift@v2
6767
with:

Package.resolved

+65-13
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,68 @@
11
{
2-
"object": {
3-
"pins": [
4-
{
5-
"package": "swift-nio",
6-
"repositoryURL": "https://github.com/apple/swift-nio.git",
7-
"state": {
8-
"branch": null,
9-
"revision": "51c3fc2e4a0fcdf4a25089b288dd65b73df1b0ef",
10-
"version": "2.37.0"
11-
}
2+
"pins" : [
3+
{
4+
"identity" : "async-collections",
5+
"kind" : "remoteSourceControl",
6+
"location" : "https://github.com/adam-fowler/async-collections",
7+
"state" : {
8+
"revision" : "726af96095a19df6b8053ddbaed0a727aa70ccb2",
9+
"version" : "0.1.0"
1210
}
13-
]
14-
},
15-
"version": 1
11+
},
12+
{
13+
"identity" : "swift-algorithms",
14+
"kind" : "remoteSourceControl",
15+
"location" : "https://github.com/apple/swift-algorithms.git",
16+
"state" : {
17+
"revision" : "f6919dfc309e7f1b56224378b11e28bab5bccc42",
18+
"version" : "1.2.0"
19+
}
20+
},
21+
{
22+
"identity" : "swift-atomics",
23+
"kind" : "remoteSourceControl",
24+
"location" : "https://github.com/apple/swift-atomics.git",
25+
"state" : {
26+
"revision" : "cd142fd2f64be2100422d658e7411e39489da985",
27+
"version" : "1.2.0"
28+
}
29+
},
30+
{
31+
"identity" : "swift-collections",
32+
"kind" : "remoteSourceControl",
33+
"location" : "https://github.com/apple/swift-collections.git",
34+
"state" : {
35+
"revision" : "671108c96644956dddcd89dd59c203dcdb36cec7",
36+
"version" : "1.1.4"
37+
}
38+
},
39+
{
40+
"identity" : "swift-nio",
41+
"kind" : "remoteSourceControl",
42+
"location" : "https://github.com/apple/swift-nio.git",
43+
"state" : {
44+
"revision" : "f7dc3f527576c398709b017584392fb58592e7f5",
45+
"version" : "2.75.0"
46+
}
47+
},
48+
{
49+
"identity" : "swift-numerics",
50+
"kind" : "remoteSourceControl",
51+
"location" : "https://github.com/apple/swift-numerics.git",
52+
"state" : {
53+
"revision" : "0a5bc04095a675662cf24757cc0640aa2204253b",
54+
"version" : "1.0.2"
55+
}
56+
},
57+
{
58+
"identity" : "swift-system",
59+
"kind" : "remoteSourceControl",
60+
"location" : "https://github.com/apple/swift-system.git",
61+
"state" : {
62+
"revision" : "c8a44d836fe7913603e246acab7c528c2e780168",
63+
"version" : "1.4.0"
64+
}
65+
}
66+
],
67+
"version" : 2
1668
}

Package.swift

+21-4
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,36 @@
1-
// swift-tools-version:5.0
1+
// swift-tools-version:5.9
22
// The swift-tools-version declares the minimum version of Swift required to build this package.
33

44
import PackageDescription
55

66
let package = Package(
77
name: "DataLoader",
8+
platforms: [.macOS(.v12), .iOS(.v15), .tvOS(.v15), .watchOS(.v8)],
89
products: [
910
.library(name: "DataLoader", targets: ["DataLoader"]),
11+
.library(name: "AsyncDataLoader", targets: ["AsyncDataLoader"]),
1012
],
1113
dependencies: [
14+
.package(url: "https://github.com/apple/swift-algorithms.git", from: "1.0.0"),
15+
.package(url: "https://github.com/adam-fowler/async-collections", from: "0.0.1"),
1216
.package(url: "https://github.com/apple/swift-nio.git", from: "2.0.0"),
1317
],
1418
targets: [
15-
.target(name: "DataLoader", dependencies: ["NIO", "NIOConcurrencyHelpers"]),
19+
.target(
20+
name: "DataLoader",
21+
dependencies: [
22+
.product(name: "NIO", package: "swift-nio"),
23+
.product(name: "NIOConcurrencyHelpers", package: "swift-nio"),
24+
]
25+
),
26+
.target(
27+
name: "AsyncDataLoader",
28+
dependencies: [
29+
.product(name: "Algorithms", package: "swift-algorithms"),
30+
.product(name: "AsyncCollections", package: "async-collections"),
31+
]
32+
),
1633
.testTarget(name: "DataLoaderTests", dependencies: ["DataLoader"]),
17-
],
18-
swiftLanguageVersions: [.v5]
34+
.testTarget(name: "AsyncDataLoaderTests", dependencies: ["AsyncDataLoader"]),
35+
]
1936
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
actor Channel<Success: Sendable, Failure: Error>: Sendable {
2+
private var state = State<Success, Failure>()
3+
}
4+
5+
extension Channel {
6+
@discardableResult
7+
func fulfill(_ value: Success) async -> Bool {
8+
if await state.result == nil {
9+
await state.setResult(result: value)
10+
11+
for waiters in await state.waiters {
12+
waiters.resume(returning: value)
13+
}
14+
15+
await state.removeAllWaiters()
16+
17+
return false
18+
}
19+
20+
return true
21+
}
22+
23+
@discardableResult
24+
func fail(_ failure: Failure) async -> Bool {
25+
if await state.failure == nil {
26+
await state.setFailure(failure: failure)
27+
28+
for waiters in await state.waiters {
29+
waiters.resume(throwing: failure)
30+
}
31+
32+
await state.removeAllWaiters()
33+
34+
return false
35+
}
36+
37+
return true
38+
}
39+
40+
var value: Success {
41+
get async throws {
42+
try await withCheckedThrowingContinuation { continuation in
43+
Task {
44+
if let result = await state.result {
45+
continuation.resume(returning: result)
46+
} else if let failure = await self.state.failure {
47+
continuation.resume(throwing: failure)
48+
} else {
49+
await state.appendWaiters(waiters: continuation)
50+
}
51+
}
52+
}
53+
}
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
typealias Waiter<Success, Failure> = CheckedContinuation<Success, Error>
2+
3+
actor State<Success, Failure> {
4+
var waiters = [Waiter<Success, Failure>]()
5+
var result: Success?
6+
var failure: Failure?
7+
}
8+
9+
extension State {
10+
func setResult(result: Success) {
11+
self.result = result
12+
}
13+
14+
func setFailure(failure: Failure) {
15+
self.failure = failure
16+
}
17+
18+
func appendWaiters(waiters: Waiter<Success, Failure>...) {
19+
self.waiters.append(contentsOf: waiters)
20+
}
21+
22+
func removeAllWaiters() {
23+
waiters.removeAll()
24+
}
25+
}

0 commit comments

Comments
 (0)