1313import Swift
1414@_implementationOnly import SwiftConcurrencyInternalShims
1515
16- // ==== Task.startSynchronously ------------------------------------------------
16+ // ==== Task.immediate --------- ------------------------------------------------
1717
1818% METHOD_VARIANTS = [
1919% 'THROWING',
@@ -32,6 +32,17 @@ import Swift
3232@available(SwiftStdlib 6.2, *)
3333extension Task where Failure == ${FAILURE_TYPE} {
3434
35+ @available(SwiftStdlib 6.2, *)
36+ @available(*, deprecated, renamed: "immediate")
37+ @discardableResult
38+ public static func startSynchronously(
39+ name: String? = nil,
40+ priority: TaskPriority? = nil,
41+ @_implicitSelfCapture _ operation: __owned @isolated(any) @escaping () async throws -> Success
42+ ) -> Task<Success, ${FAILURE_TYPE}> {
43+ immediate(name: name, priority: priority, operation)
44+ }
45+
3546 /// Create and immediately start running a new task in the context of the calling thread/task.
3647 ///
3748 /// This function _starts_ the created task on the calling context.
@@ -56,17 +67,33 @@ extension Task where Failure == ${FAILURE_TYPE} {
5667 /// - Returns: A reference to the unstructured task which may be awaited on.
5768 @available(SwiftStdlib 6.2, *)
5869 @discardableResult
59- public static func startSynchronously (
70+ public static func immediate (
6071 name: String? = nil,
6172 priority: TaskPriority? = nil,
62- @_inheritActorContext @_implicitSelfCapture _ operation: __owned sending @escaping () async throws -> Success
73+ % # NOTE: This closure cannot be 'sending' because we'll trigger ' pattern that the region based isolation checker does not understand how to check'
74+ % # In this case: `func syncOnMyGlobalActor() { Task.immediate { @MyGlobalActor in } }`
75+ @_implicitSelfCapture _ operation: __owned @isolated(any) @escaping () async throws -> Success
6376 ) -> Task<Success, ${FAILURE_TYPE}> {
77+
78+ let builtinSerialExecutor =
79+ unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
80+
81+ // Determine if we're switching isolation dynamically.
82+ // If not, we can run the task synchronously and therefore MUST NOT "enqueue" it.
83+ let flagsMustNotCrash: UInt64 = 0
84+ let canRunSynchronously: Bool =
85+ if let builtinSerialExecutor {
86+ _taskIsCurrentExecutor(executor: builtinSerialExecutor, flags: flagsMustNotCrash)
87+ } else {
88+ true // if there is not target executor, we can run synchronously
89+ }
90+
6491 let flags = taskCreateFlags(
6592 priority: priority,
6693 isChildTask: false,
6794 copyTaskLocals: true,
6895 inheritContext: true,
69- enqueueJob: false, // don't enqueue, we'll run it manually
96+ enqueueJob: !canRunSynchronously,
7097 addPendingGroupTaskUnconditionally: false,
7198 isDiscardingTask: false,
7299 isSynchronousStart: true
@@ -79,6 +106,7 @@ extension Task where Failure == ${FAILURE_TYPE} {
79106 unsafe name.utf8CString.withUnsafeBufferPointer { nameBytes in
80107 Builtin.createTask(
81108 flags: flags,
109+ initialSerialExecutor: builtinSerialExecutor,
82110 taskName: nameBytes.baseAddress!._rawValue,
83111 operation: operation).0
84112 }
@@ -91,7 +119,9 @@ extension Task where Failure == ${FAILURE_TYPE} {
91119 operation: operation).0
92120 }
93121
94- _startTaskSynchronously(task!)
122+ if canRunSynchronously {
123+ _startTaskImmediately(task!, targetExecutor: builtinSerialExecutor)
124+ }
95125 return Task<Success, ${FAILURE_TYPE}>(task!)
96126 }
97127}
@@ -102,35 +132,35 @@ GROUP_AND_OP_INFO = [
102132 (
103133 'TaskGroup',
104134 [
105- 'startTaskSynchronously ',
106- 'startTaskSynchronouslyUnlessCancelled '
135+ 'addImmediateTask ',
136+ 'addImmediateTaskUnlessCancelled '
107137 ],
108138 '',
109139 'ChildTaskResult'
110140 ),
111141 (
112142 'ThrowingTaskGroup',
113143 [
114- 'startTaskSynchronously ',
115- 'startTaskSynchronouslyUnlessCancelled '
144+ 'addImmediateTask ',
145+ 'addImmediateTaskUnlessCancelled '
116146 ],
117147 'throws ',
118148 'ChildTaskResult'
119149 ),
120150 (
121151 'DiscardingTaskGroup',
122152 [
123- 'startTaskSynchronously ',
124- 'startTaskSynchronouslyUnlessCancelled '
153+ 'addImmediateTask ',
154+ 'addImmediateTaskUnlessCancelled '
125155 ],
126156 '',
127157 'Void'
128158 ),
129159 (
130160 'ThrowingDiscardingTaskGroup',
131161 [
132- 'startTaskSynchronously ',
133- 'startTaskSynchronouslyUnlessCancelled '
162+ 'addImmediateTask ',
163+ 'addImmediateTaskUnlessCancelled '
134164 ],
135165 'throws ',
136166 'Void'
@@ -161,7 +191,7 @@ extension ${GROUP_TYPE} {
161191 public func ${METHOD_NAME}( // in ${GROUP_TYPE}
162192 name: String? = nil,
163193 priority: TaskPriority? = nil,
164- operation: sending @escaping () async ${THROWS}-> ${RESULT_TYPE}
194+ @_inheritActorContext @_implicitSelfCapture operation: sending @isolated(any) @escaping () async ${THROWS}-> ${RESULT_TYPE}
165195 ) {
166196 let flags = taskCreateFlags(
167197 priority: priority,
@@ -174,13 +204,18 @@ extension ${GROUP_TYPE} {
174204 isSynchronousStart: true
175205 )
176206
207+ // Create the asynchronous task.
208+ let builtinSerialExecutor =
209+ unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
210+
177211 // Create the task in this group.
178212 let (task, _) = Builtin.createTask(
179213 flags: flags,
214+ initialSerialExecutor: builtinSerialExecutor,
180215 taskGroup: self._group,
181216 operation: operation
182217 )
183- _startTaskSynchronously (task)
218+ _startTaskImmediately (task, targetExecutor: builtinSerialExecutor )
184219 }
185220}
186221% end # METHOD_NAMES
@@ -240,5 +275,5 @@ extension Task where Failure == ${FAILURE_TYPE} {
240275@_silgen_name("swift_task_startOnMainActor")
241276internal func _startTaskOnMainActor(_ task: Builtin.NativeObject)
242277
243- @_silgen_name("swift_task_startSynchronously ")
244- internal func _startTaskSynchronously (_ task: Builtin.NativeObject)
278+ @_silgen_name("swift_task_immediate ")
279+ internal func _startTaskImmediately (_ task: Builtin.NativeObject, targetExecutor: Builtin.Executor? )
0 commit comments