13
13
import Swift
14
14
@_implementationOnly import SwiftConcurrencyInternalShims
15
15
16
+ // ==== Task.startSynchronously ------------------------------------------------
17
+
16
18
% METHOD_VARIANTS = [
17
19
% 'THROWING',
18
20
% 'NON_THROWING',
19
21
% ]
20
- % OPERATION_PARAM = '@_inheritActorContext @_implicitSelfCapture _ operation: __owned @Sendable @escaping @MainActor () async throws -> Success'
22
+ % OPERATION_PARAM = '@_inheritActorContext @_implicitSelfCapture _ operation: __owned @Sendable @escaping () async throws -> Success'
21
23
% for METHOD_VARIANT in METHOD_VARIANTS:
22
24
23
25
% IS_THROWING = METHOD_VARIANT == 'THROWING'
@@ -27,8 +29,6 @@ import Swift
27
29
% FAILURE_TYPE = 'Never'
28
30
% end
29
31
30
- // ==== Task.startSynchronously ------------------------------------------------
31
-
32
32
@available(SwiftStdlib 6.2, *)
33
33
extension Task where Failure == ${FAILURE_TYPE} {
34
34
@@ -55,9 +55,9 @@ extension Task where Failure == ${FAILURE_TYPE} {
55
55
/// - Returns: A reference to the unstructured task which may be awaited on.
56
56
@available(SwiftStdlib 6.2, *)
57
57
@discardableResult
58
- public static func _startSynchronously (
58
+ public static func startSynchronously (
59
59
priority: TaskPriority? = nil,
60
- @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> Success
60
+ @_inheritActorContext @_implicitSelfCapture _ operation: __owned sending @escaping () async throws -> Success
61
61
) -> Task<Success, ${FAILURE_TYPE}> {
62
62
let flags = taskCreateFlags(
63
63
priority: priority,
@@ -75,8 +75,121 @@ extension Task where Failure == ${FAILURE_TYPE} {
75
75
return Task<Success, ${FAILURE_TYPE}>(task)
76
76
}
77
77
}
78
+ %end
79
+
80
+ % OPERATION_PARAM = 'operation: sending @escaping () async throws -> ChildTaskResult'
81
+ % for (GROUP_TYPE, METHOD_NAMES) in [
82
+ % (
83
+ % 'TaskGroup',
84
+ % [
85
+ % 'startTaskSynchronously',
86
+ % 'startTaskSynchronouslyUnlessCancelled'
87
+ % ]
88
+ % ),
89
+ % (
90
+ % 'ThrowingTaskGroup',
91
+ % [
92
+ % 'startTaskSynchronously',
93
+ % 'startTaskSynchronouslyUnlessCancelled'
94
+ % ]
95
+ % ),
96
+ % (
97
+ % 'DiscardingTaskGroup',
98
+ % [
99
+ % 'startTaskSynchronously',
100
+ % 'startTaskSynchronouslyUnlessCancelled'
101
+ % ]
102
+ % ),
103
+ % (
104
+ % 'ThrowingDiscardingTaskGroup',
105
+ % [
106
+ % 'startTaskSynchronously',
107
+ % 'startTaskSynchronouslyUnlessCancelled'
108
+ % ]
109
+ % ),
110
+ % ]:
111
+ % for METHOD_NAME in METHOD_NAMES:
112
+
113
+ % IS_DISCARDING = 'Discarding' in GROUP_TYPE
114
+ % IS_THROWING = 'Throwing' in GROUP_TYPE
115
+
116
+ % if not IS_THROWING:
117
+ % OPERATION_PARAM = OPERATION_PARAM.replace('throws', '')
118
+ % end
119
+
120
+ % if IS_DISCARDING:
121
+ % OPERATION_PARAM = OPERATION_PARAM.replace('ChildTaskResult', 'Void')
122
+ % end
123
+
124
+ % if IS_THROWING:
125
+ % FAILURE_TYPE = 'Error'
126
+ % else:
127
+ % FAILURE_TYPE = 'Never'
128
+ % end
129
+
130
+ @available(SwiftStdlib 6.2, *)
131
+ extension ${GROUP_TYPE} {
132
+
133
+ /// Create and immediately start running a new child task in the context of the calling thread/task.
134
+ ///
135
+ /// This function _starts_ the created task on the calling context.
136
+ /// The task will continue executing on the caller's context until it suspends,
137
+ /// and after suspension will resume on the adequate executor. For a nonisolated
138
+ /// operation this means running on the global concurrent pool, and on an isolated
139
+ /// operation it means the appropriate executor of that isolation context.
140
+ ///
141
+ /// As indicated by the lack of `async` on this method, this method does _not_
142
+ /// suspend, and instead takes over the calling task's (thread's) execution in
143
+ /// a synchronous manner.
144
+ ///
145
+ /// Other than the execution semantics discussed above, the created task
146
+ /// is semantically equivalent to its basic version which can be
147
+ /// created using ``${GROUP_TYPE}/addTask``.
148
+ @available(SwiftStdlib 6.2, *)
149
+ public func ${METHOD_NAME}( // in ${GROUP_TYPE}
150
+ priority: TaskPriority? = nil,
151
+ ${OPERATION_PARAM}
152
+ ) {
153
+ let flags = taskCreateFlags(
154
+ priority: priority,
155
+ isChildTask: true,
156
+ copyTaskLocals: false,
157
+ inheritContext: false,
158
+ enqueueJob: false, // don't enqueue, we'll run it manually
159
+ addPendingGroupTaskUnconditionally: true,
160
+ isDiscardingTask: false,
161
+ isSynchronousStart: false
162
+ )
163
+
164
+ // Create the task in this group.
165
+ let (task, _) = Builtin.createTask(
166
+ flags: flags,
167
+ taskGroup: self._group,
168
+ operation: operation
169
+ )
170
+ _startTaskSynchronously(task)
171
+ }
172
+ }
173
+ %end # METHOD_NAMES
174
+ %end # GROUP_TYPES
78
175
79
176
// ==== Legacy SPI -------------------------------------------------------------
177
+
178
+ % METHOD_VARIANTS = [
179
+ % 'THROWING',
180
+ % 'NON_THROWING',
181
+ % ]
182
+ % OPERATION_PARAM = '@_inheritActorContext @_implicitSelfCapture _ operation: __owned @Sendable @escaping @MainActor () async throws -> Success'
183
+ % for METHOD_VARIANT in METHOD_VARIANTS:
184
+
185
+ % IS_THROWING = METHOD_VARIANT == 'THROWING'
186
+ % if IS_THROWING:
187
+ % FAILURE_TYPE = 'Error'
188
+ % else:
189
+ % FAILURE_TYPE = 'Never'
190
+ % OPERATION_PARAM = OPERATION_PARAM.replace('throws', '')
191
+ % end
192
+
80
193
#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY && !SWIFT_CONCURRENCY_EMBEDDED
81
194
@available(SwiftStdlib 5.9, *)
82
195
extension Task where Failure == ${FAILURE_TYPE} {
@@ -87,7 +200,7 @@ extension Task where Failure == ${FAILURE_TYPE} {
87
200
@discardableResult
88
201
public static func startOnMainActor(
89
202
priority: TaskPriority? = nil,
90
- ${OPERATION_PARAM if IS_THROWING else OPERATION_PARAM.replace("throws", "") }
203
+ ${OPERATION_PARAM}
91
204
) -> Task<Success, ${FAILURE_TYPE}> {
92
205
let flags = taskCreateFlags(
93
206
priority: priority,
0 commit comments