@@ -5,6 +5,24 @@ import NIO
5
5
6
6
#if compiler(>=5.5) && canImport(_Concurrency)
7
7
8
+ @available ( macOS 12 , iOS 15 , watchOS 8 , tvOS 15 , * )
9
+ actor Concurrent < T> {
10
+ var wrappedValue : T
11
+
12
+ func nonmutating< Returned> ( _ action: ( T ) throws -> Returned ) async rethrows -> Returned {
13
+ try action ( wrappedValue)
14
+ }
15
+
16
+ func mutating< Returned> ( _ action: ( inout T ) throws -> Returned ) async rethrows -> Returned {
17
+ try action ( & wrappedValue)
18
+ }
19
+
20
+ init ( _ value: T ) {
21
+ self . wrappedValue = value
22
+ }
23
+ }
24
+
25
+
8
26
/// Primary API
9
27
@available ( macOS 12 , iOS 15 , watchOS 8 , tvOS 15 , * )
10
28
final class DataLoaderAsyncTests : XCTestCase {
@@ -61,15 +79,7 @@ final class DataLoaderAsyncTests: XCTestCase {
61
79
XCTAssertNoThrow ( try eventLoopGroup. syncShutdownGracefully ( ) )
62
80
}
63
81
64
- actor LoadCalls {
65
- var loadCalls = [ [ Int] ] ( )
66
-
67
- func append( _ calls: [ Int ] ) {
68
- loadCalls. append ( calls)
69
- }
70
-
71
- static let shared : LoadCalls = . init( )
72
- }
82
+ let loadCalls = Concurrent < [ [ Int ] ] > ( [ ] )
73
83
74
84
let identityLoader = DataLoader < Int , Int > (
75
85
on: eventLoopGroup. next ( ) ,
@@ -78,35 +88,28 @@ final class DataLoaderAsyncTests: XCTestCase {
78
88
executionPeriod: nil
79
89
)
80
90
) { keys in
81
- await LoadCalls . shared . append ( keys)
91
+ await loadCalls . mutating { $0 . append ( keys) }
82
92
let task = Task {
83
93
keys. map { DataLoaderFutureValue . success ( $0) }
84
94
}
85
95
return await task. value
86
96
}
87
97
88
- // Normally async-let is a better option that using explicit Task, but the test machine fails to use async let multiple times already
89
- // async let value1 = identityLoader.load(key: 1, on: eventLoopGroup)
90
- // async let value2 = identityLoader.load(key: 2, on: eventLoopGroup)
91
- let value1 = Task {
92
- try await identityLoader. load ( key: 1 , on: eventLoopGroup)
93
- }
94
- let value2 = Task {
95
- try await identityLoader. load ( key: 2 , on: eventLoopGroup)
96
- }
98
+ async let value1 = identityLoader. load ( key: 1 , on: eventLoopGroup)
99
+ async let value2 = identityLoader. load ( key: 2 , on: eventLoopGroup)
97
100
98
101
/// Have to wait for a split second because Tasks may not be executed before this statement
99
102
try await Task . sleep ( nanoseconds: 500_000_000 )
100
103
101
104
XCTAssertNoThrow ( try identityLoader. execute ( ) )
102
105
103
- let result1 = try await value1. value
106
+ let result1 = try await value1
104
107
XCTAssertEqual ( result1, 1 )
105
- let result2 = try await value2. value
108
+ let result2 = try await value2
106
109
XCTAssertEqual ( result2, 2 )
107
110
108
- let loadCalls = await LoadCalls . shared . loadCalls
109
- XCTAssertEqual ( loadCalls , [ [ 1 , 2 ] ] )
111
+ let calls = await loadCalls. wrappedValue
112
+ XCTAssertEqual ( calls , [ [ 1 , 2 ] ] )
110
113
}
111
114
}
112
115
0 commit comments