Skip to content

Commit a27f65d

Browse files
ktosoallevato
andauthored
Apply suggestions from code review
Co-authored-by: Tony Allevato <[email protected]>
1 parent 59b9d9c commit a27f65d

File tree

1 file changed

+16
-16
lines changed

1 file changed

+16
-16
lines changed

proposals/NNNN-task-start-synchronously-on-caller-context.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
Swift Concurrency's primary means of entering an asynchronous context is creating a Task (structured or unstructured), and from there onwards it is possible to call asynchronous functions, and execution of the current work may _suspend_.
1313

14-
Entering the asynchronous context today incurs the creating and scheduling of a task to be executed at some later point in time. This initial delay may be wasteful for tasks which perform minimal or none (!) work at all.
14+
Entering the asynchronous context today incurs the creating and scheduling of a task to be executed at some later point in time. This initial delay may be wasteful for tasks which perform minimal or no (!) work at all.
1515

1616
This initial delay may also be problematic for some situations where it is known that we are executing on the "right actor" however are *not* in an asynchronous function and therefore in order to call some different asynchronous function we must create a new task and introduce subtle timing differences as compared to just being able to call the target function–which may be isolated to the same actor we're calling from–immediately.
1717

@@ -51,7 +51,7 @@ func synchronousFunction() {
5151
}
5252
```
5353

54-
The above example showcases a typical situation where this new API can be useful. While `assumeIsolated` gives us a specific isolation... it still would not allow us to call arbitrary async functions, as we are still in a synchronous context.
54+
The above example showcases a typical situation where this new API can be useful. While `assumeIsolated` gives us a specific isolation, it still would not allow us to call arbitrary async functions, as we are still in a synchronous context.
5555

5656
The proposed `Task.startSynchronously` API forms an async context on the calling thread/task/executor, and therefore allows us to call into async code, at the risk of overhanging on the calling executor. So while this should be used sparingly, it allows entering an asynchronous context *synchronously*.
5757

@@ -102,18 +102,18 @@ extension Task {
102102

103103
@discardableResult
104104
public static func startSynchronously(
105-
// SE-NNNN's proposed 'name: String? = nil' would be here
105+
// SE-0469's proposed 'name: String? = nil' would be here if accepted
106106
priority: TaskPriority? = nil,
107107
executorPreference taskExecutor: consuming (any TaskExecutor)? = nil,
108-
operation: sending @escaping async throws(Failure) -> Success,
108+
operation: sending @escaping async throws(Failure) -> Success
109109
) -> Task<Success, Failure>
110110

111111
@discardableResult
112112
public static func startSynchronouslyDetached(
113-
// SE-NNNN's proposed 'name: String? = nil' would be here
113+
// SE-0469's proposed 'name: String? = nil' would be here if accepted
114114
priority: TaskPriority? = nil,
115115
executorPreference taskExecutor: consuming (any TaskExecutor)? = nil,
116-
operation: sending @escaping async throws(Failure) -> Success,
116+
operation: sending @escaping async throws(Failure) -> Success
117117
) -> Task<Success, Failure>
118118
}
119119
```
@@ -125,41 +125,41 @@ extension (Throwing)TaskGroup {
125125

126126
// Same add semantics as 'addTask'.
127127
func startTaskSynchronously(
128-
// SE-NNNN's proposed 'name: String? = nil' would be here
128+
// SE-0469's proposed 'name: String? = nil' would be here
129129
priority: TaskPriority? = nil,
130130
executorPreference taskExecutor: (any TaskExecutor)? = nil,
131-
operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult
131+
operation: sending @escaping () async throws -> ChildTaskResult
132132
)
133133

134134
// Same add semantics as 'addTaskUnlessCancelled'.
135135
func startTaskSynchronouslyUnlessCancelled(
136-
// SE-NNNN's proposed 'name: String? = nil' would be here
136+
// SE-0469's proposed 'name: String? = nil' would be here
137137
priority: TaskPriority? = nil,
138138
executorPreference taskExecutor: (any TaskExecutor)? = nil,
139-
operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult
139+
operation: sending @escaping () async throws -> ChildTaskResult
140140
)
141141
}
142142

143143
extension (Throwing)DiscardingTaskGroup {
144144
// Same add semantics as 'addTask'.
145145
func startTaskSynchronously(
146-
// SE-NNNN's proposed 'name: String? = nil' would be here
146+
// SE-0469's proposed 'name: String? = nil' would be here
147147
priority: TaskPriority? = nil,
148148
executorPreference taskExecutor: (any TaskExecutor)? = nil,
149-
operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult
149+
operation: sending @escaping () async throws -> ChildTaskResult
150150
)
151151

152152
// Same add semantics as 'addTaskUnlessCancelled'.
153153
func startTaskSynchronouslyUnlessCancelled(
154-
// SE-NNNN's proposed 'name: String? = nil' would be here
154+
// SE-0469's proposed 'name: String? = nil' would be here
155155
priority: TaskPriority? = nil,
156156
executorPreference taskExecutor: (any TaskExecutor)? = nil,
157-
operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult
157+
operation: sending @escaping () async throws -> ChildTaskResult
158158
)
159159
}
160160
```
161161

162-
The `startTaskSynchronously` mirrors the functionality of `addTask`, unconditionally adding the task to the group, while the `startTaskSynchronouslyUnlessCancelled` mirrors the `addTaskUnlessCancelled` which only adds the task to the group if the group (or task we're running in, and therefore the group as well) are not cancelled.
162+
The `startTaskSynchronously` function mirrors the functionality of `addTask`, unconditionally adding the task to the group, while the `startTaskSynchronouslyUnlessCancelled` mirrors the `addTaskUnlessCancelled` which only adds the task to the group if the group (or task we're running in, and therefore the group as well) are not cancelled.
163163

164164
### Isolation rules
165165

@@ -256,7 +256,7 @@ After the suspension point though, there may have been other tasks executed on t
256256

257257
Synchronously started tasks behave exactly the same as their fully asynchronous equivalents.
258258

259-
In short, cancellation, and priority escalation remains automatic for structured tasks created using TaskGroup APIs, however they do not propagate automatically for unstructured tasks created using the `Task.startSynchronously[Detached](...)` APIs. Task locals and base priority also functions the same way as usual;
259+
In short, cancellation, and priority escalation remains automatic for structured tasks created using TaskGroup APIs, however they do not propagate automatically for unstructured tasks created using the `Task.startSynchronously[Detached](...)` APIs. Task locals and base priority also functions the same way as usual.
260260

261261
The only difference in behavior is where these synchronously started tasks _begin_ their execution.
262262

0 commit comments

Comments
 (0)