@@ -88,12 +88,12 @@ public final class AsyncChannel<Element: Sendable>: AsyncSequence, Sendable {
88
88
case idle
89
89
case pending( Set < Pending > )
90
90
case awaiting( Set < Awaiting > )
91
+ case finished
91
92
}
92
93
93
94
struct State {
94
95
var emission : Emission = . idle
95
96
var generation = 0
96
- var terminal = false
97
97
}
98
98
99
99
let state = ManagedCriticalState ( State ( ) )
@@ -145,10 +145,6 @@ public final class AsyncChannel<Element: Sendable>: AsyncSequence, Sendable {
145
145
return nil
146
146
}
147
147
148
- if state. terminal {
149
- terminal = true
150
- return nil
151
- }
152
148
switch state. emission {
153
149
case . idle:
154
150
state. emission = . awaiting( [ Awaiting ( generation: generation, continuation: continuation) ] )
@@ -165,6 +161,9 @@ public final class AsyncChannel<Element: Sendable>: AsyncSequence, Sendable {
165
161
nexts. update ( with: Awaiting ( generation: generation, continuation: continuation) )
166
162
state. emission = . awaiting( nexts)
167
163
return nil
164
+ case . finished:
165
+ terminal = true
166
+ return nil
168
167
}
169
168
} ? . resume ( )
170
169
@@ -205,7 +204,7 @@ public final class AsyncChannel<Element: Sendable>: AsyncSequence, Sendable {
205
204
let continuation = await withUnsafeContinuation { continuation in
206
205
state. withCriticalRegion { state -> UnsafeResumption < UnsafeContinuation < Element ? , Never > ? , Never > ? in
207
206
208
- if sendTokenStatus. withCriticalRegion ( { $0 } ) == . cancelled || state . terminal {
207
+ if sendTokenStatus. withCriticalRegion ( { $0 } ) == . cancelled {
209
208
return UnsafeResumption ( continuation: continuation, success: nil )
210
209
}
211
210
@@ -225,6 +224,8 @@ public final class AsyncChannel<Element: Sendable>: AsyncSequence, Sendable {
225
224
state. emission = . awaiting( nexts)
226
225
}
227
226
return UnsafeResumption ( continuation: continuation, success: next)
227
+ case . finished:
228
+ return UnsafeResumption ( continuation: continuation, success: nil )
228
229
}
229
230
} ? . resume ( )
230
231
}
@@ -249,20 +250,22 @@ public final class AsyncChannel<Element: Sendable>: AsyncSequence, Sendable {
249
250
/// All subsequent calls to `next(_:)` will resume immediately.
250
251
public func finish( ) {
251
252
let ( sends, nexts) = state. withCriticalRegion { state -> ( Set < Pending > , Set < Awaiting > ) in
252
- if state. terminal {
253
- return ( [ ] , [ ] )
254
- }
255
- state. terminal = true
253
+ let result : ( Set < Pending > , Set < Awaiting > )
254
+
256
255
switch state. emission {
257
256
case . idle:
258
- return ( [ ] , [ ] )
257
+ result = ( [ ] , [ ] )
259
258
case . pending( let nexts) :
260
- state. emission = . idle
261
- return ( nexts, [ ] )
259
+ result = ( nexts, [ ] )
262
260
case . awaiting( let nexts) :
263
- state. emission = . idle
264
- return ( [ ] , nexts)
261
+ result = ( [ ] , nexts)
262
+ case . finished:
263
+ result = ( [ ] , [ ] )
265
264
}
265
+
266
+ state. emission = . finished
267
+
268
+ return result
266
269
}
267
270
for send in sends {
268
271
send. continuation? . resume ( returning: nil )
0 commit comments