@@ -60,29 +60,12 @@ public final class ActorQueue<ActorType: Actor>: @unchecked Sendable {
60
60
let ( taskStream, taskStreamContinuation) = AsyncStream< ActorTask> . makeStream( )
61
61
self . taskStreamContinuation = taskStreamContinuation
62
62
63
- func beginExecuting(
64
- _ operation: sending @escaping ( isolated ActorType) async -> Void ,
65
- in context: isolated ActorType,
66
- priority: TaskPriority ?
67
- ) {
68
- // In Swift 6, a `Task` enqueued from an actor begins executing immediately on that actor.
69
- // Since we're running on our actor's context already, we can just dispatch a Task to get first-enqueued-first-start task execution.
70
- Task ( priority: priority) {
71
- await operation ( context)
72
- }
73
- }
74
-
75
63
Task {
76
64
// In an ideal world, we would isolate this `for await` loop to the `ActorType`.
77
65
// However, there's no good way to do that without retaining the actor and creating a cycle.
78
66
for await actorTask in taskStream {
79
67
// Await switching to the ActorType context.
80
- await beginExecuting (
81
- actorTask. task,
82
- in: actorTask. executionContext,
83
- priority: actorTask. priority
84
- )
85
- await actorTask. sempahore. signal ( )
68
+ await actorTask. task ( actorTask. executionContext)
86
69
}
87
70
}
88
71
}
@@ -120,17 +103,13 @@ public final class ActorQueue<ActorType: Actor>: @unchecked Sendable {
120
103
fileprivate struct ActorTask : Sendable {
121
104
init (
122
105
executionContext: ActorType ,
123
- priority: TaskPriority ? ,
124
106
task: @escaping @Sendable ( isolated ActorType) async -> Void
125
107
) {
126
108
self . executionContext = executionContext
127
- self . priority = priority
128
109
self . task = task
129
110
}
130
-
111
+
131
112
let executionContext : ActorType
132
- let sempahore = Semaphore ( )
133
- let priority : TaskPriority ?
134
113
let task : @Sendable ( isolated ActorType) async -> Void
135
114
}
136
115
@@ -177,17 +156,25 @@ extension Task {
177
156
operation: @Sendable @escaping ( isolated ActorType) async -> Success
178
157
) where Failure == Never {
179
158
let delivery = Delivery < Success , Failure > ( )
159
+ let semaphore = Semaphore ( )
180
160
let task = ActorQueue< ActorType> . ActorTask(
181
161
executionContext: actorQueue. executionContext,
182
- priority: priority,
183
162
task: { executionContext in
184
- await delivery. sendValue ( operation ( executionContext) )
163
+ await semaphore. wait ( )
164
+ delivery. execute ( { @Sendable executionContext in
165
+ await delivery. sendValue ( operation ( executionContext) )
166
+ } , in: executionContext, priority: priority)
185
167
}
186
168
)
187
169
actorQueue. taskStreamContinuation. yield ( task)
188
170
self . init ( priority: priority) {
189
- await task. sempahore. wait ( )
190
- return await delivery. getValue ( )
171
+ await withTaskCancellationHandler (
172
+ operation: {
173
+ await semaphore. signal ( )
174
+ return await delivery. getValue ( )
175
+ } ,
176
+ onCancel: delivery. cancel
177
+ )
191
178
}
192
179
}
193
180
@@ -224,22 +211,29 @@ extension Task {
224
211
operation: @escaping @Sendable ( isolated ActorType) async throws -> Success
225
212
) where Failure == any Error {
226
213
let delivery = Delivery < Success , Failure > ( )
214
+ let semaphore = Semaphore ( )
227
215
let task = ActorQueue< ActorType> . ActorTask(
228
216
executionContext: actorQueue. executionContext,
229
- priority: priority,
230
217
task: { executionContext in
231
- do {
232
- try await delivery. sendValue ( operation ( executionContext) )
233
- } catch {
234
- await delivery. sendFailure ( error)
235
- }
218
+ await semaphore. wait ( )
219
+ delivery. execute ( { @Sendable executionContext in
220
+ do {
221
+ try await delivery. sendValue ( operation ( executionContext) )
222
+ } catch {
223
+ await delivery. sendFailure ( error)
224
+ }
225
+ } , in: executionContext, priority: priority)
236
226
}
237
227
)
238
-
239
228
actorQueue. taskStreamContinuation. yield ( task)
240
229
self . init ( priority: priority) {
241
- await task. sempahore. wait ( )
242
- return try await delivery. getValue ( )
230
+ try await withTaskCancellationHandler (
231
+ operation: {
232
+ await semaphore. signal ( )
233
+ return try await delivery. getValue ( )
234
+ } ,
235
+ onCancel: delivery. cancel
236
+ )
243
237
}
244
238
}
245
239
@@ -276,17 +270,25 @@ extension Task {
276
270
operation: @MainActor @escaping ( ) async -> Success
277
271
) where Failure == Never {
278
272
let delivery = Delivery < Success , Failure > ( )
273
+ let semaphore = Semaphore ( )
279
274
let task = ActorQueue< MainActor> . ActorTask(
280
275
executionContext: actorQueue. executionContext,
281
- priority: priority,
282
276
task: { executionContext in
283
- await delivery. sendValue ( operation ( ) )
277
+ await semaphore. wait ( )
278
+ delivery. execute ( { @Sendable executionContext in
279
+ await delivery. sendValue ( operation ( ) )
280
+ } , in: executionContext, priority: priority)
284
281
}
285
282
)
286
283
actorQueue. taskStreamContinuation. yield ( task)
287
284
self . init ( priority: priority) {
288
- await task. sempahore. wait ( )
289
- return await delivery. getValue ( )
285
+ return await withTaskCancellationHandler (
286
+ operation: {
287
+ await semaphore. signal ( )
288
+ return await delivery. getValue ( )
289
+ } ,
290
+ onCancel: delivery. cancel
291
+ )
290
292
}
291
293
}
292
294
@@ -323,22 +325,29 @@ extension Task {
323
325
operation: @escaping @MainActor ( ) async throws -> Success
324
326
) where Failure == any Error {
325
327
let delivery = Delivery < Success , Failure > ( )
328
+ let semaphore = Semaphore ( )
326
329
let task = ActorQueue< MainActor> . ActorTask(
327
330
executionContext: actorQueue. executionContext,
328
- priority: priority,
329
331
task: { executionContext in
330
- do {
331
- try await delivery. sendValue ( operation ( ) )
332
- } catch {
333
- await delivery. sendFailure ( error)
334
- }
332
+ await semaphore. wait ( )
333
+ delivery. execute ( { @Sendable executionContext in
334
+ do {
335
+ try await delivery. sendValue ( operation ( ) )
336
+ } catch {
337
+ await delivery. sendFailure ( error)
338
+ }
339
+ } , in: executionContext, priority: priority)
335
340
}
336
341
)
337
-
338
342
actorQueue. taskStreamContinuation. yield ( task)
339
343
self . init ( priority: priority) {
340
- await task. sempahore. wait ( )
341
- return try await delivery. getValue ( )
344
+ try await withTaskCancellationHandler (
345
+ operation: {
346
+ await semaphore. signal ( )
347
+ return try await delivery. getValue ( )
348
+ } ,
349
+ onCancel: delivery. cancel
350
+ )
342
351
}
343
352
}
344
353
}
0 commit comments