@@ -17,7 +17,7 @@ import Swift
17
17
import Darwin
18
18
19
19
func _lockWordCount( ) -> Int {
20
- let sz =
20
+ let sz =
21
21
MemoryLayout < os_unfair_lock > . size / MemoryLayout < UnsafeRawPointer > . size
22
22
return max ( sz, 1 )
23
23
}
@@ -57,7 +57,7 @@ extension AsyncStream {
57
57
typealias TerminationHandler = @Sendable ( Continuation . Termination ) -> Void
58
58
59
59
struct State {
60
- var continuation : UnsafeContinuation < Element ? , Never > ?
60
+ var continuations = [ UnsafeContinuation < Element ? , Never > ] ( )
61
61
var pending = _Deque < Element > ( )
62
62
let limit : Continuation . BufferingPolicy
63
63
var onTermination : TerminationHandler ?
@@ -105,7 +105,7 @@ extension AsyncStream {
105
105
}
106
106
}
107
107
108
- func cancel( ) {
108
+ @ Sendable func cancel( ) {
109
109
lock ( )
110
110
// swap out the handler before we invoke it to prevent double cancel
111
111
let handler = state. onTermination
@@ -123,7 +123,9 @@ extension AsyncStream {
123
123
lock ( )
124
124
let limit = state. limit
125
125
let count = state. pending. count
126
- if let continuation = state. continuation {
126
+
127
+ if !state. continuations. isEmpty {
128
+ let continuation = state. continuations. removeFirst ( )
127
129
if count > 0 {
128
130
if !state. terminal {
129
131
switch limit {
@@ -151,17 +153,14 @@ extension AsyncStream {
151
153
} else {
152
154
result = . terminated
153
155
}
154
- state. continuation = nil
155
156
let toSend = state. pending. removeFirst ( )
156
157
unlock ( )
157
158
continuation. resume ( returning: toSend)
158
159
} else if state. terminal {
159
- state. continuation = nil
160
160
result = . terminated
161
161
unlock ( )
162
162
continuation. resume ( returning: nil )
163
163
} else {
164
- state. continuation = nil
165
164
switch limit {
166
165
case . unbounded:
167
166
result = . enqueued( remaining: . max)
@@ -212,15 +211,15 @@ extension AsyncStream {
212
211
state. onTermination = nil
213
212
state. terminal = true
214
213
215
- if let continuation = state. continuation {
214
+ if let continuation = state. continuations . first {
216
215
if state. pending. count > 0 {
217
- state. continuation = nil
216
+ state. continuations . removeFirst ( )
218
217
let toSend = state. pending. removeFirst ( )
219
218
unlock ( )
220
219
handler ? ( . finished)
221
220
continuation. resume ( returning: toSend)
222
221
} else if state. terminal {
223
- state. continuation = nil
222
+ state. continuations . removeFirst ( )
224
223
unlock ( )
225
224
handler ? ( . finished)
226
225
continuation. resume ( returning: nil )
@@ -236,22 +235,20 @@ extension AsyncStream {
236
235
237
236
func next( _ continuation: UnsafeContinuation < Element ? , Never > ) {
238
237
lock ( )
239
- if state. continuation == nil {
240
- if state. pending. count > 0 {
241
- let toSend = state. pending. removeFirst ( )
242
- unlock ( )
243
- continuation. resume ( returning: toSend)
244
- } else if state. terminal {
245
- unlock ( )
246
- continuation. resume ( returning: nil )
247
- } else {
248
- state. continuation = continuation
249
- unlock ( )
250
- }
238
+ state. continuations. append ( continuation)
239
+ if state. pending. count > 0 {
240
+ let cont = state. continuations. removeFirst ( )
241
+ let toSend = state. pending. removeFirst ( )
242
+ unlock ( )
243
+ cont. resume ( returning: toSend)
244
+ } else if state. terminal {
245
+ let cont = state. continuations. removeFirst ( )
246
+ unlock ( )
247
+ cont. resume ( returning: nil )
251
248
} else {
252
249
unlock ( )
253
- fatalError ( " attempt to await next() on more than one task " )
254
250
}
251
+
255
252
}
256
253
257
254
func next( ) async -> Element ? {
@@ -341,7 +338,7 @@ extension AsyncThrowingStream {
341
338
}
342
339
}
343
340
344
- func cancel( ) {
341
+ @ Sendable func cancel( ) {
345
342
lock ( )
346
343
// swap out the handler before we invoke it to prevent double cancel
347
344
let handler = state. onTermination
@@ -595,3 +592,4 @@ final class _AsyncStreamCriticalStorage<Contents>: @unchecked Sendable {
595
592
return storage
596
593
}
597
594
}
595
+
0 commit comments