13
13
import Swift
14
14
@_implementationOnly import _SwiftConcurrencyShims
15
15
16
- // ==== Task Nursery -----------------------------------------------------------
16
+ // ==== Task Group -- -----------------------------------------------------------
17
17
18
18
extension Task {
19
19
20
- /// Starts a new nursery which provides a scope in which a dynamic number of
20
+ /// Starts a new task group which provides a scope in which a dynamic number of
21
21
/// tasks may be spawned.
22
22
///
23
- /// Tasks added to the nursery by `nursery.add()` will automatically be
24
- /// awaited on when the scope exits.
23
+ /// Tasks added to the group by `group.add()` will automatically be awaited on
24
+ /// when the scope exits. If the group exits by throwing, all added tasks will
25
+ /// be cancelled and their results discarded.
25
26
///
26
27
/// ### Implicit awaiting
27
- /// When results of tasks added to the nursery need to be collected, one will
28
- /// gather task's results using the `while let result = await nursery.next() { ... }`
29
- /// pattern.
28
+ /// When results of tasks added to the group need to be collected, one can
29
+ /// gather their results using the following pattern:
30
+ ///
31
+ /// while let result = await group.next() {
32
+ /// // some accumulation logic (e.g. sum += result)
33
+ /// }
30
34
///
31
35
/// ### Cancellation
32
- /// If any of the tasks throws the nursery and all of its tasks will be cancelled,
33
- /// and the error will be re-thrown by `withNursery`.
36
+ /// If an error is thrown out of the task group, all of its remaining tasks
37
+ /// will be cancelled and the `withGroup` call will rethrow that error.
38
+ ///
39
+ /// Individual tasks throwing results in their corresponding `try group.next()`
40
+ /// call throwing, giving a chance to handle individual errors or letting the
41
+ /// error be rethrown by the group.
34
42
///
35
43
/// Postcondition:
36
- /// Once `withNursery ` returns it is guaranteed that the *nursery* is *empty*.
44
+ /// Once `withGroup ` returns it is guaranteed that the `group` is *empty*.
37
45
///
38
46
/// This is achieved in the following way:
39
47
/// - if the body returns normally:
40
- /// - the nursery will await any not yet complete tasks,
48
+ /// - the group will await any not yet complete tasks,
41
49
/// - if any of those tasks throws, the remaining tasks will be cancelled,
42
- /// - once the `withNursery ` returns the nursery is guaranteed to be empty.
50
+ /// - once the `withGroup ` returns the group is guaranteed to be empty.
43
51
/// - if the body throws:
44
- /// - all tasks remaining in the nursery will be automatically cancelled.
45
- ///
46
- // TODO: Do we have to add a different nursery type to accommodate throwing
52
+ /// - all tasks remaining in the group will be automatically cancelled.
53
+ // TODO: Do we have to add a different group type to accommodate throwing
47
54
// tasks without forcing users to use Result? I can't think of how that
48
55
// could be propagated out of the callback body reasonably, unless we
49
56
// commit to doing multi-statement closure typechecking.
50
- public static func withNursery < TaskResult, BodyResult> (
57
+ public static func withGroup < TaskResult, BodyResult> (
51
58
resultType: TaskResult . Type ,
52
59
returning returnType: BodyResult . Type = BodyResult . self,
53
- body: ( inout Nursery < TaskResult > ) async throws -> BodyResult
60
+ body: ( inout Task . Group < TaskResult > ) async throws -> BodyResult
54
61
) async rethrows -> BodyResult {
55
62
fatalError ( " \( #function) not implemented yet. " )
56
63
}
57
64
58
- /// A nursery provides a scope within which a dynamic number of tasks may be
59
- /// started and added to the nursery.
65
+ /// A task group serves as storage for dynamically started tasks.
66
+ ///
67
+ /// Its intended use is with the
60
68
/* @unmoveable */
61
- public struct Nursery < TaskResult> {
69
+ public struct Group < TaskResult> {
62
70
/// No public initializers
63
71
private init ( ) { }
64
72
65
73
// Swift will statically prevent this type from being copied or moved.
66
74
// For now, that implies that it cannot be used with generics.
67
75
68
- /// Add a child task to the nursery .
76
+ /// Add a child task to the group .
69
77
///
70
78
/// ### Error handling
71
79
/// Operations are allowed to throw.
@@ -75,7 +83,7 @@ extension Task {
75
83
///
76
84
/// - Parameters:
77
85
/// - overridingPriority: override priority of the operation task
78
- /// - operation: operation to execute and add to the nursery
86
+ /// - operation: operation to execute and add to the group
79
87
public mutating func add(
80
88
overridingPriority: Priority ? = nil ,
81
89
operation: ( ) async throws -> TaskResult
@@ -86,11 +94,11 @@ extension Task {
86
94
/// Add a child task and return a `Task.Handle` that can be used to manage it.
87
95
///
88
96
/// The task's result is accessible either via the returned `handle` or the
89
- /// `nursery .next()` function (as any other `add`-ed task).
97
+ /// `group .next()` function (as any other `add`-ed task).
90
98
///
91
99
/// - Parameters:
92
100
/// - overridingPriority: override priority of the operation task
93
- /// - operation: operation to execute and add to the nursery
101
+ /// - operation: operation to execute and add to the group
94
102
public mutating func addWithHandle(
95
103
overridingPriority: Priority ? = nil ,
96
104
operation: ( ) async throws -> TaskResult
@@ -106,20 +114,20 @@ extension Task {
106
114
fatalError ( " \( #function) not implemented yet. " )
107
115
}
108
116
109
- /// Query whether the nursery has any remaining tasks.
117
+ /// Query whether the group has any remaining tasks.
110
118
///
111
- /// Nurseries are always empty upon entry to the `withNursery ` body, and
112
- /// become empty again when `withNursery ` returns (either by awaiting on all
119
+ /// Task groups are always empty upon entry to the `withGroup ` body, and
120
+ /// become empty again when `withGroup ` returns (either by awaiting on all
113
121
/// pending tasks or cancelling them).
114
122
///
115
- /// - Returns: `true` if the nursery has no pending tasks, `false` otherwise.
123
+ /// - Returns: `true` if the group has no pending tasks, `false` otherwise.
116
124
public var isEmpty : Bool {
117
125
fatalError ( " \( #function) not implemented yet. " )
118
126
}
119
127
120
- /// Cancel all the remaining tasks in the nursery .
128
+ /// Cancel all the remaining tasks in the group .
121
129
///
122
- /// A cancelled nursery will not will NOT accept new tasks being added into it.
130
+ /// A cancelled group will not will NOT accept new tasks being added into it.
123
131
///
124
132
/// Any results, including errors thrown by tasks affected by this
125
133
/// cancellation, are silently discarded.
0 commit comments