@@ -39,7 +39,7 @@ final class ZipStorage<Base1: AsyncSequence, Base2: AsyncSequence, Base3: AsyncS
39
39
func next( ) async rethrows -> ( Base1 . Element , Base2 . Element , Base3 . Element ? ) ? {
40
40
try await withTaskCancellationHandler {
41
41
let result = await withUnsafeContinuation { continuation in
42
- self . stateMachine. withCriticalRegion { stateMachine in
42
+ let action : StateMachine . NextAction ? = self . stateMachine. withCriticalRegion { stateMachine in
43
43
let action = stateMachine. next ( for: continuation)
44
44
switch action {
45
45
case . startTask( let base1, let base2, let base3) :
@@ -51,42 +51,59 @@ final class ZipStorage<Base1: AsyncSequence, Base2: AsyncSequence, Base3: AsyncS
51
51
base3: base3,
52
52
downstreamContinuation: continuation
53
53
)
54
+ return nil
54
55
55
- case . resumeUpstreamContinuations( let upstreamContinuations) :
56
- // bases can be iterated over for 1 iteration so their next value can be retrieved
57
- upstreamContinuations. forEach { $0. resume ( ) }
56
+ case . resumeUpstreamContinuations:
57
+ return action
58
58
59
- case . resumeDownstreamContinuationWithNil( let continuation) :
60
- // the async sequence is already finished, immediately resuming
61
- continuation. resume ( returning: . success( nil ) )
59
+ case . resumeDownstreamContinuationWithNil:
60
+ return action
62
61
}
63
62
}
63
+
64
+ switch action {
65
+ case . startTask:
66
+ // We are handling the startTask in the lock already because we want to avoid
67
+ // other inputs interleaving while starting the task
68
+ fatalError ( " Internal inconsistency " )
69
+
70
+ case . resumeUpstreamContinuations( let upstreamContinuations) :
71
+ // bases can be iterated over for 1 iteration so their next value can be retrieved
72
+ upstreamContinuations. forEach { $0. resume ( ) }
73
+
74
+ case . resumeDownstreamContinuationWithNil( let continuation) :
75
+ // the async sequence is already finished, immediately resuming
76
+ continuation. resume ( returning: . success( nil ) )
77
+
78
+ case . none:
79
+ break
80
+ }
64
81
}
65
82
66
83
return try result. _rethrowGet ( )
67
84
68
85
} onCancel: {
69
- self . stateMachine. withCriticalRegion { stateMachine in
70
- let action = stateMachine. cancelled ( )
86
+ let action = self . stateMachine. withCriticalRegion { stateMachine in
87
+ stateMachine. cancelled ( )
88
+ }
71
89
72
- switch action {
73
- case . resumeDownstreamContinuationWithNilAndCancelTaskAndUpstreamContinuations(
74
- let downstreamContinuation,
75
- let task,
76
- let upstreamContinuations
77
- ) :
78
- upstreamContinuations. forEach { $0. resume ( throwing: CancellationError ( ) ) }
79
- task. cancel ( )
90
+ switch action {
91
+ case . resumeDownstreamContinuationWithNilAndCancelTaskAndUpstreamContinuations(
92
+ let downstreamContinuation,
93
+ let task,
94
+ let upstreamContinuations
95
+ ) :
96
+ upstreamContinuations. forEach { $0. resume ( throwing: CancellationError ( ) ) }
97
+ task. cancel ( )
80
98
81
- downstreamContinuation. resume ( returning: . success( nil ) )
99
+ downstreamContinuation. resume ( returning: . success( nil ) )
82
100
83
- case . cancelTaskAndUpstreamContinuations( let task, let upstreamContinuations) :
84
- upstreamContinuations. forEach { $0. resume ( throwing: CancellationError ( ) ) }
85
- task. cancel ( )
101
+ case . cancelTaskAndUpstreamContinuations( let task, let upstreamContinuations) :
102
+ upstreamContinuations. forEach { $0. resume ( throwing: CancellationError ( ) ) }
103
+ task. cancel ( )
86
104
87
- case . none:
88
- break
89
- }
105
+ case . none:
106
+ break
90
107
}
91
108
}
92
109
}
@@ -112,53 +129,53 @@ final class ZipStorage<Base1: AsyncSequence, Base2: AsyncSequence, Base3: AsyncS
112
129
// element from upstream. This continuation is only resumed
113
130
// if the downstream consumer called `next` to signal his demand.
114
131
try await withUnsafeThrowingContinuation { continuation in
115
- self . stateMachine. withCriticalRegion { stateMachine in
116
- let action = stateMachine. childTaskSuspended ( baseIndex: 0 , continuation: continuation)
132
+ let action = self . stateMachine. withCriticalRegion { stateMachine in
133
+ stateMachine. childTaskSuspended ( baseIndex: 0 , continuation: continuation)
134
+ }
117
135
118
- switch action {
119
- case . resumeContinuation( let upstreamContinuation) :
120
- upstreamContinuation. resume ( )
136
+ switch action {
137
+ case . resumeContinuation( let upstreamContinuation) :
138
+ upstreamContinuation. resume ( )
121
139
122
- case . resumeContinuationWithError( let upstreamContinuation, let error) :
123
- upstreamContinuation. resume ( throwing: error)
140
+ case . resumeContinuationWithError( let upstreamContinuation, let error) :
141
+ upstreamContinuation. resume ( throwing: error)
124
142
125
- case . none:
126
- break
127
- }
143
+ case . none:
144
+ break
128
145
}
129
146
}
130
147
131
148
if let element1 = try await base1Iterator. next ( ) {
132
- self . stateMachine. withCriticalRegion { stateMachine in
133
- let action = stateMachine. elementProduced ( ( element1, nil , nil ) )
149
+ let action = self . stateMachine. withCriticalRegion { stateMachine in
150
+ stateMachine. elementProduced ( ( element1, nil , nil ) )
151
+ }
134
152
135
- switch action {
136
- case . resumeContinuation( let downstreamContinuation, let result) :
137
- downstreamContinuation. resume ( returning: result)
153
+ switch action {
154
+ case . resumeContinuation( let downstreamContinuation, let result) :
155
+ downstreamContinuation. resume ( returning: result)
138
156
139
- case . none:
140
- break
141
- }
157
+ case . none:
158
+ break
142
159
}
143
160
} else {
144
- self . stateMachine. withCriticalRegion { stateMachine in
145
- let action = stateMachine. upstreamFinished ( )
161
+ let action = self . stateMachine. withCriticalRegion { stateMachine in
162
+ stateMachine. upstreamFinished ( )
163
+ }
146
164
147
- switch action {
148
- case . resumeContinuationWithNilAndCancelTaskAndUpstreamContinuations(
149
- let downstreamContinuation,
150
- let task,
151
- let upstreamContinuations
152
- ) :
165
+ switch action {
166
+ case . resumeContinuationWithNilAndCancelTaskAndUpstreamContinuations(
167
+ let downstreamContinuation,
168
+ let task,
169
+ let upstreamContinuations
170
+ ) :
153
171
154
- upstreamContinuations. forEach { $0. resume ( throwing: CancellationError ( ) ) }
155
- task. cancel ( )
172
+ upstreamContinuations. forEach { $0. resume ( throwing: CancellationError ( ) ) }
173
+ task. cancel ( )
156
174
157
- downstreamContinuation. resume ( returning: . success( nil ) )
175
+ downstreamContinuation. resume ( returning: . success( nil ) )
158
176
159
- case . none:
160
- break
161
- }
177
+ case . none:
178
+ break
162
179
}
163
180
}
164
181
}
@@ -172,53 +189,53 @@ final class ZipStorage<Base1: AsyncSequence, Base2: AsyncSequence, Base3: AsyncS
172
189
// element from upstream. This continuation is only resumed
173
190
// if the downstream consumer called `next` to signal his demand.
174
191
try await withUnsafeThrowingContinuation { continuation in
175
- self . stateMachine. withCriticalRegion { stateMachine in
176
- let action = stateMachine. childTaskSuspended ( baseIndex: 1 , continuation: continuation)
192
+ let action = self . stateMachine. withCriticalRegion { stateMachine in
193
+ stateMachine. childTaskSuspended ( baseIndex: 1 , continuation: continuation)
194
+ }
177
195
178
- switch action {
179
- case . resumeContinuation( let upstreamContinuation) :
180
- upstreamContinuation. resume ( )
196
+ switch action {
197
+ case . resumeContinuation( let upstreamContinuation) :
198
+ upstreamContinuation. resume ( )
181
199
182
- case . resumeContinuationWithError( let upstreamContinuation, let error) :
183
- upstreamContinuation. resume ( throwing: error)
200
+ case . resumeContinuationWithError( let upstreamContinuation, let error) :
201
+ upstreamContinuation. resume ( throwing: error)
184
202
185
- case . none:
186
- break
187
- }
203
+ case . none:
204
+ break
188
205
}
189
206
}
190
207
191
208
if let element2 = try await base2Iterator. next ( ) {
192
- self . stateMachine. withCriticalRegion { stateMachine in
193
- let action = stateMachine. elementProduced ( ( nil , element2, nil ) )
209
+ let action = self . stateMachine. withCriticalRegion { stateMachine in
210
+ stateMachine. elementProduced ( ( nil , element2, nil ) )
211
+ }
194
212
195
- switch action {
196
- case . resumeContinuation( let downstreamContinuation, let result) :
197
- downstreamContinuation. resume ( returning: result)
213
+ switch action {
214
+ case . resumeContinuation( let downstreamContinuation, let result) :
215
+ downstreamContinuation. resume ( returning: result)
198
216
199
- case . none:
200
- break
201
- }
217
+ case . none:
218
+ break
202
219
}
203
220
} else {
204
- self . stateMachine. withCriticalRegion { stateMachine in
205
- let action = stateMachine. upstreamFinished ( )
221
+ let action = self . stateMachine. withCriticalRegion { stateMachine in
222
+ stateMachine. upstreamFinished ( )
223
+ }
206
224
207
- switch action {
208
- case . resumeContinuationWithNilAndCancelTaskAndUpstreamContinuations(
209
- let downstreamContinuation,
210
- let task,
211
- let upstreamContinuations
212
- ) :
225
+ switch action {
226
+ case . resumeContinuationWithNilAndCancelTaskAndUpstreamContinuations(
227
+ let downstreamContinuation,
228
+ let task,
229
+ let upstreamContinuations
230
+ ) :
213
231
214
- upstreamContinuations. forEach { $0. resume ( throwing: CancellationError ( ) ) }
215
- task. cancel ( )
232
+ upstreamContinuations. forEach { $0. resume ( throwing: CancellationError ( ) ) }
233
+ task. cancel ( )
216
234
217
- downstreamContinuation. resume ( returning: . success( nil ) )
235
+ downstreamContinuation. resume ( returning: . success( nil ) )
218
236
219
- case . none:
220
- break
221
- }
237
+ case . none:
238
+ break
222
239
}
223
240
}
224
241
}
@@ -233,53 +250,53 @@ final class ZipStorage<Base1: AsyncSequence, Base2: AsyncSequence, Base3: AsyncS
233
250
// element from upstream. This continuation is only resumed
234
251
// if the downstream consumer called `next` to signal his demand.
235
252
try await withUnsafeThrowingContinuation { continuation in
236
- self . stateMachine. withCriticalRegion { stateMachine in
237
- let action = stateMachine. childTaskSuspended ( baseIndex: 2 , continuation: continuation)
253
+ let action = self . stateMachine. withCriticalRegion { stateMachine in
254
+ stateMachine. childTaskSuspended ( baseIndex: 2 , continuation: continuation)
255
+ }
238
256
239
- switch action {
240
- case . resumeContinuation( let upstreamContinuation) :
241
- upstreamContinuation. resume ( )
257
+ switch action {
258
+ case . resumeContinuation( let upstreamContinuation) :
259
+ upstreamContinuation. resume ( )
242
260
243
- case . resumeContinuationWithError( let upstreamContinuation, let error) :
244
- upstreamContinuation. resume ( throwing: error)
261
+ case . resumeContinuationWithError( let upstreamContinuation, let error) :
262
+ upstreamContinuation. resume ( throwing: error)
245
263
246
- case . none:
247
- break
248
- }
264
+ case . none:
265
+ break
249
266
}
250
267
}
251
268
252
269
if let element3 = try await base3Iterator. next ( ) {
253
- self . stateMachine. withCriticalRegion { stateMachine in
254
- let action = stateMachine. elementProduced ( ( nil , nil , element3) )
270
+ let action = self . stateMachine. withCriticalRegion { stateMachine in
271
+ stateMachine. elementProduced ( ( nil , nil , element3) )
272
+ }
255
273
256
- switch action {
257
- case . resumeContinuation( let downstreamContinuation, let result) :
258
- downstreamContinuation. resume ( returning: result)
274
+ switch action {
275
+ case . resumeContinuation( let downstreamContinuation, let result) :
276
+ downstreamContinuation. resume ( returning: result)
259
277
260
- case . none:
261
- break
262
- }
278
+ case . none:
279
+ break
263
280
}
264
281
} else {
265
- self . stateMachine. withCriticalRegion { stateMachine in
266
- let action = stateMachine. upstreamFinished ( )
282
+ let action = self . stateMachine. withCriticalRegion { stateMachine in
283
+ stateMachine. upstreamFinished ( )
284
+ }
267
285
268
- switch action {
269
- case . resumeContinuationWithNilAndCancelTaskAndUpstreamContinuations(
270
- let downstreamContinuation,
271
- let task,
272
- let upstreamContinuations
273
- ) :
286
+ switch action {
287
+ case . resumeContinuationWithNilAndCancelTaskAndUpstreamContinuations(
288
+ let downstreamContinuation,
289
+ let task,
290
+ let upstreamContinuations
291
+ ) :
274
292
275
- upstreamContinuations. forEach { $0. resume ( throwing: CancellationError ( ) ) }
276
- task. cancel ( )
293
+ upstreamContinuations. forEach { $0. resume ( throwing: CancellationError ( ) ) }
294
+ task. cancel ( )
277
295
278
- downstreamContinuation. resume ( returning: . success( nil ) )
296
+ downstreamContinuation. resume ( returning: . success( nil ) )
279
297
280
- case . none:
281
- break
282
- }
298
+ case . none:
299
+ break
283
300
}
284
301
}
285
302
}
@@ -291,25 +308,25 @@ final class ZipStorage<Base1: AsyncSequence, Base2: AsyncSequence, Base3: AsyncS
291
308
try await group. next ( )
292
309
} catch {
293
310
// One of the upstream sequences threw an error
294
- self . stateMachine. withCriticalRegion { stateMachine in
295
- let action = stateMachine. upstreamThrew ( error)
296
- switch action {
297
- case . resumeContinuationWithErrorAndCancelTaskAndUpstreamContinuations (
298
- let downstreamContinuation ,
299
- let error ,
300
- let task ,
301
- let upstreamContinuations
302
- ) :
303
- upstreamContinuations . forEach { $0 . resume ( throwing : CancellationError ( ) ) }
304
- task . cancel ( )
305
-
306
- downstreamContinuation . resume ( returning : . failure ( error ) )
307
- case . none :
308
- break
309
- }
310
- }
311
+ let action = self . stateMachine. withCriticalRegion { stateMachine in
312
+ stateMachine. upstreamThrew ( error)
313
+ }
314
+ switch action {
315
+ case . resumeContinuationWithErrorAndCancelTaskAndUpstreamContinuations (
316
+ let downstreamContinuation ,
317
+ let error ,
318
+ let task ,
319
+ let upstreamContinuations
320
+ ) :
321
+ upstreamContinuations . forEach { $0 . resume ( throwing : CancellationError ( ) ) }
322
+ task . cancel ( )
323
+
324
+ downstreamContinuation . resume ( returning : . failure ( error ) )
325
+ case . none :
326
+ break
327
+ }
311
328
312
- group. cancelAll ( )
329
+ group. cancelAll ( )
313
330
}
314
331
}
315
332
}
0 commit comments