@@ -220,22 +220,17 @@ public struct TaskGroup<ChildTaskResult: Sendable> {
220
220
/// - Returns:
221
221
/// - `true` if the operation was added to the group successfully,
222
222
/// `false` otherwise (e.g. because the group `isCancelled`)
223
- @discardableResult
224
223
public mutating func spawn(
225
- overridingPriority priorityOverride : Task . Priority ? = nil ,
224
+ priority : Task . Priority = . unspecified ,
226
225
operation: __owned @Sendable @escaping ( ) async -> ChildTaskResult
227
- ) -> Self . Spawned {
228
- let canAdd = _taskGroupAddPendingTask ( group: _group)
229
-
230
- guard canAdd else {
231
- // the group is cancelled and is not accepting any new work
232
- return Spawned ( handle: nil )
233
- }
226
+ ) {
227
+ _ = _taskGroupAddPendingTask ( group: _group, unconditionally: true )
234
228
235
229
// Set up the job flags for a new task.
236
230
var flags = Task . JobFlags ( )
237
231
flags. kind = . task
238
- flags. priority = priorityOverride ?? getJobFlags ( _task) . priority
232
+ flags. priority = priority != Task . Priority. unspecified ?
233
+ priority : getJobFlags ( _task) . priority
239
234
flags. isFuture = true
240
235
flags. isChildTask = true
241
236
flags. isGroupChildTask = true
@@ -249,25 +244,56 @@ public struct TaskGroup<ChildTaskResult: Sendable> {
249
244
250
245
// Enqueue the resulting job.
251
246
_enqueueJobGlobal ( Builtin . convertTaskToJob ( childTask) )
252
-
253
- return Spawned ( handle: Task . Handle ( childTask) )
254
247
}
255
248
256
- public struct Spawned : Sendable {
257
- /// Returns `true` if the task was successfully spawned in the task group,
258
- /// `false` otherwise which means that the group was already cancelled and
259
- /// refused to accept spawn a new child task.
260
- public var successfully : Bool { handle != nil }
261
-
262
- /// Task handle for the spawned task group child task,
263
- /// or `nil` if it was not spawned successfully.
264
- public let handle : Task . Handle < ChildTaskResult , Never > ?
249
+ /// Add a child task to the group.
250
+ ///
251
+ /// ### Error handling
252
+ /// Operations are allowed to `throw`, in which case the `try await next()`
253
+ /// invocation corresponding to the failed task will re-throw the given task.
254
+ ///
255
+ /// The `add` function will never (re-)throw errors from the `operation`.
256
+ /// Instead, the corresponding `next()` call will throw the error when necessary.
257
+ ///
258
+ /// - Parameters:
259
+ /// - overridingPriority: override priority of the operation task
260
+ /// - operation: operation to execute and add to the group
261
+ /// - Returns:
262
+ /// - `true` if the operation was added to the group successfully,
263
+ /// `false` otherwise (e.g. because the group `isCancelled`)
264
+ public mutating func spawnUnlessCancelled(
265
+ priority: Task . Priority = . unspecified,
266
+ operation: __owned @Sendable @escaping ( ) async -> ChildTaskResult
267
+ ) -> Bool {
268
+ let canAdd = _taskGroupAddPendingTask ( group: _group, unconditionally: false )
265
269
266
- init ( handle: Task . Handle < ChildTaskResult , Never > ? ) {
267
- self . handle = handle
270
+ guard canAdd else {
271
+ // the group is cancelled and is not accepting any new work
272
+ return false
268
273
}
274
+
275
+ // Set up the job flags for a new task.
276
+ var flags = Task . JobFlags ( )
277
+ flags. kind = . task
278
+ flags. priority = priority != Task . Priority. unspecified ?
279
+ priority : getJobFlags ( _task) . priority
280
+ flags. isFuture = true
281
+ flags. isChildTask = true
282
+ flags. isGroupChildTask = true
283
+
284
+ // Create the asynchronous task future.
285
+ let ( childTask, _) = Builtin . createAsyncTaskGroupFuture (
286
+ flags. bits, _group, operation)
287
+
288
+ // Attach it to the group's task record in the current task.
289
+ _ = _taskGroupAttachChild ( group: _group, child: childTask)
290
+
291
+ // Enqueue the resulting job.
292
+ _enqueueJobGlobal ( Builtin . convertTaskToJob ( childTask) )
293
+
294
+ return true
269
295
}
270
-
296
+
271
297
/// Wait for the a child task that was added to the group to complete,
272
298
/// and return (or rethrow) the value it completed with. If no tasks are
273
299
/// pending in the task group this function returns `nil`, allowing the
@@ -417,7 +443,7 @@ public struct ThrowingTaskGroup<ChildTaskResult: Sendable, Failure: Error> {
417
443
self . _group = group
418
444
}
419
445
420
- /// Add a child task to the group.
446
+ /// Spawn, unconditionally, a child task in the group.
421
447
///
422
448
/// ### Error handling
423
449
/// Operations are allowed to `throw`, in which case the `try await next()`
@@ -432,22 +458,64 @@ public struct ThrowingTaskGroup<ChildTaskResult: Sendable, Failure: Error> {
432
458
/// - Returns:
433
459
/// - `true` if the operation was added to the group successfully,
434
460
/// `false` otherwise (e.g. because the group `isCancelled`)
435
- @discardableResult
436
461
public mutating func spawn(
437
- overridingPriority priorityOverride : Task . Priority ? = nil ,
462
+ priority : Task . Priority = . unspecified ,
438
463
operation: __owned @Sendable @escaping ( ) async throws -> ChildTaskResult
439
- ) -> Self . Spawned {
440
- let canAdd = _taskGroupAddPendingTask ( group: _group)
464
+ ) {
465
+ // we always add, so no need to check if group was cancelled
466
+ _ = _taskGroupAddPendingTask ( group: _group, unconditionally: true )
467
+
468
+ // Set up the job flags for a new task.
469
+ var flags = Task . JobFlags ( )
470
+ flags. kind = . task
471
+ flags. priority = priority != Task . Priority. unspecified ?
472
+ priority : getJobFlags ( _task) . priority
473
+ flags. isFuture = true
474
+ flags. isChildTask = true
475
+ flags. isGroupChildTask = true
476
+
477
+ // Create the asynchronous task future.
478
+ let ( childTask, _) = Builtin . createAsyncTaskGroupFuture (
479
+ flags. bits, _group, operation)
480
+
481
+ // Attach it to the group's task record in the current task.
482
+ _ = _taskGroupAttachChild ( group: _group, child: childTask)
483
+
484
+ // Enqueue the resulting job.
485
+ _enqueueJobGlobal ( Builtin . convertTaskToJob ( childTask) )
486
+ }
487
+
488
+ /// Add a child task to the group.
489
+ ///
490
+ /// ### Error handling
491
+ /// Operations are allowed to `throw`, in which case the `try await next()`
492
+ /// invocation corresponding to the failed task will re-throw the given task.
493
+ ///
494
+ /// The `add` function will never (re-)throw errors from the `operation`.
495
+ /// Instead, the corresponding `next()` call will throw the error when necessary.
496
+ ///
497
+ /// - Parameters:
498
+ /// - overridingPriority: override priority of the operation task
499
+ /// - operation: operation to execute and add to the group
500
+ /// - Returns:
501
+ /// - `true` if the operation was added to the group successfully,
502
+ /// `false` otherwise (e.g. because the group `isCancelled`)
503
+ public mutating func spawnUnlessCancelled(
504
+ priority: Task . Priority = . unspecified,
505
+ operation: __owned @Sendable @escaping ( ) async throws -> ChildTaskResult
506
+ ) -> Bool {
507
+ let canAdd = _taskGroupAddPendingTask ( group: _group, unconditionally: false )
441
508
442
509
guard canAdd else {
443
510
// the group is cancelled and is not accepting any new work
444
- return Spawned ( handle : nil )
511
+ return false
445
512
}
446
513
447
514
// Set up the job flags for a new task.
448
515
var flags = Task . JobFlags ( )
449
516
flags. kind = . task
450
- flags. priority = priorityOverride ?? getJobFlags ( _task) . priority
517
+ flags. priority = priority != Task . Priority. unspecified ?
518
+ priority : getJobFlags ( _task) . priority
451
519
flags. isFuture = true
452
520
flags. isChildTask = true
453
521
flags. isGroupChildTask = true
@@ -462,22 +530,7 @@ public struct ThrowingTaskGroup<ChildTaskResult: Sendable, Failure: Error> {
462
530
// Enqueue the resulting job.
463
531
_enqueueJobGlobal ( Builtin . convertTaskToJob ( childTask) )
464
532
465
- return Spawned ( handle: Task . Handle ( childTask) )
466
- }
467
-
468
- public struct Spawned : Sendable {
469
- /// Returns `true` if the task was successfully spawned in the task group,
470
- /// `false` otherwise which means that the group was already cancelled and
471
- /// refused to accept spawn a new child task.
472
- public var successfully : Bool { handle != nil }
473
-
474
- /// Task handle for the spawned task group child task,
475
- /// or `nil` if it was not spawned successfully.
476
- public let handle : Task . Handle < ChildTaskResult , Error > ?
477
-
478
- init ( handle: Task . Handle < ChildTaskResult , Error > ? ) {
479
- self . handle = handle
480
- }
533
+ return true
481
534
}
482
535
483
536
/// Wait for the a child task that was added to the group to complete,
@@ -754,7 +807,8 @@ func _taskGroupDestroy(group: __owned Builtin.RawPointer)
754
807
@available( macOS 9999 , iOS 9999 , watchOS 9999 , tvOS 9999 , * )
755
808
@_silgen_name( " swift_taskGroup_addPending" )
756
809
func _taskGroupAddPendingTask(
757
- group: Builtin . RawPointer
810
+ group: Builtin . RawPointer ,
811
+ unconditionally: Bool
758
812
) -> Bool
759
813
760
814
@available ( macOS 9999 , iOS 9999 , watchOS 9999 , tvOS 9999 , * )
0 commit comments