@@ -129,7 +129,12 @@ public final class AsyncThrowingChannel<Element: Sendable, Failure: Error>: Asyn
129
129
func next( _ generation: Int ) async throws -> Element ? {
130
130
return try await withUnsafeThrowingContinuation { continuation in
131
131
var cancelled = false
132
+ var isTerminal = false
132
133
state. withCriticalRegion { state -> UnsafeResumption < UnsafeContinuation < Element ? , Error > ? , Never > ? in
134
+ if state. terminal {
135
+ isTerminal = true
136
+ return nil
137
+ }
133
138
switch state. emission {
134
139
case . idle:
135
140
state. emission = . awaiting( [ Awaiting ( generation: generation, continuation: continuation) ] )
@@ -155,13 +160,13 @@ public final class AsyncThrowingChannel<Element: Sendable, Failure: Error>: Asyn
155
160
return nil
156
161
}
157
162
} ? . resume ( )
158
- if cancelled {
163
+ if cancelled || isTerminal {
159
164
continuation. resume ( returning: nil )
160
165
}
161
166
}
162
167
}
163
168
164
- func cancelSend ( ) {
169
+ func finishAll ( ) {
165
170
let ( sends, nexts) = state. withCriticalRegion { state -> ( [ UnsafeContinuation < UnsafeContinuation < Element ? , Error > ? , Never > ] , Set < Awaiting > ) in
166
171
if state. terminal {
167
172
return ( [ ] , [ ] )
@@ -186,23 +191,20 @@ public final class AsyncThrowingChannel<Element: Sendable, Failure: Error>: Asyn
186
191
}
187
192
}
188
193
189
- func _send( _ result: Result < Element ? , Error > ) async {
194
+ func _send( _ result: Result < Element , Error > ) async {
190
195
await withTaskCancellationHandler {
191
- cancelSend ( )
196
+ finishAll ( )
192
197
} operation: {
193
198
let continuation : UnsafeContinuation < Element ? , Error > ? = await withUnsafeContinuation { continuation in
194
199
state. withCriticalRegion { state -> UnsafeResumption < UnsafeContinuation < Element ? , Error > ? , Never > ? in
195
200
if state. terminal {
196
201
return UnsafeResumption ( continuation: continuation, success: nil )
197
202
}
198
- switch result {
199
- case . success( let value) :
200
- if value == nil {
201
- state. terminal = true
202
- }
203
- case . failure:
203
+
204
+ if case . failure = result {
204
205
state. terminal = true
205
206
}
207
+
206
208
switch state. emission {
207
209
case . idle:
208
210
state. emission = . pending( [ continuation] )
@@ -222,7 +224,7 @@ public final class AsyncThrowingChannel<Element: Sendable, Failure: Error>: Asyn
222
224
}
223
225
} ? . resume ( )
224
226
}
225
- continuation? . resume ( with: result)
227
+ continuation? . resume ( with: result. map { $0 as Element ? } )
226
228
}
227
229
}
228
230
@@ -238,10 +240,9 @@ public final class AsyncThrowingChannel<Element: Sendable, Failure: Error>: Asyn
238
240
await _send ( . failure( error) )
239
241
}
240
242
241
- /// Send a finish to an awaiting iteration. This function will resume when the next call to `next()` is made.
242
- /// If the channel is already finished then this returns immediately
243
- public func finish( ) async {
244
- await _send ( . success( nil ) )
243
+ /// Send a finish to all awaiting iterations.
244
+ public func finish( ) {
245
+ finishAll ( )
245
246
}
246
247
247
248
public func makeAsyncIterator( ) -> Iterator {
0 commit comments