You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: proposals/0471-SerialExecutor-isIsolated.md
+51Lines changed: 51 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -135,6 +135,52 @@ The general guidance about which method to implement is to implement `isIsolatin
135
135
136
136
The runtime will always invoke the `isIsolatingCurrentContext` before making attempts to call `checkIsolated`, and if the prior returns either `true` or `false`, the latter (`checkIsolated`) will not be invoked at all.
137
137
138
+
### Checking if currently isolated to some `Actor`
139
+
140
+
We also introduce a way to obtain `SerialExecutor` from an `Actor`, which was previously not possible.
141
+
142
+
This API needs to be scoped because the lifetime of the serial executor must be tied to the Actor's lifetime:
143
+
144
+
```swift
145
+
extensionActor {
146
+
/// Perform an operation with the actor's ``SerialExecutor``.
147
+
///
148
+
/// This converts the actor's ``Actor/unownedExecutor`` to a ``SerialExecutor`` while
149
+
/// retaining the actor for the duration of the operation. This is to ensure the lifetime
150
+
/// of the executor while performing the operation.
151
+
@_alwaysEmitIntoClient
152
+
@available(SwiftStdlib 5.1, *)
153
+
publicnonisolatedfuncwithSerialExecutor<T>(_operation: (any SerialExecutor) throws-> T) rethrows-> T
154
+
155
+
/// Perform an operation with the actor's ``SerialExecutor``.
156
+
///
157
+
/// This converts the actor's ``Actor/unownedExecutor`` to a ``SerialExecutor`` while
158
+
/// retaining the actor for the duration of the operation. This is to ensure the lifetime
159
+
/// of the executor while performing the operation.
160
+
@_alwaysEmitIntoClient
161
+
@available(SwiftStdlib 5.1, *)
162
+
publicnonisolatedfuncwithSerialExecutor<T>(_operation: (any SerialExecutor) asyncthrows-> T) asyncrethrows-> T
163
+
164
+
}
165
+
```
166
+
167
+
This allows developers to write "warn if wrong isolation" code, before moving on to enable preconditions in a future release of a library. This gives library developers, and their adopters, time to adjust their code usage before enabling more strict validation mode in the future, for example like this:
warn("'something' must be called from the same isolation as the operation closure is isolated to!"+
174
+
"This will become a runtime crash in future releases of this library.")
175
+
}
176
+
}
177
+
}
178
+
```
179
+
180
+
181
+
182
+
This API will be backdeployed and will be available independently of runtime version of the concurrency runtime.
183
+
138
184
### Compatibility strategy for custom SerialExecutor authors
139
185
140
186
New executor implementations should prioritize implementing `isIsolatingCurrentContext` when available, using an appropriate `#if swift(>=...)` check to ensure compatibility. Otherwise, they should fall back to implementing the crashing version of this API: `checkIsolated()`.
@@ -169,7 +215,12 @@ This would be ideal, however also problematic since changing a protocol requirem
169
215
170
216
In order to make adoption of this new mode less painful and not cause deprecation warnings to libraries which intend to support multiple versions of Swift, the `SerialExcecutor/checkIsolated` protocol requirement remains _not_ deprecated. It may eventually become deprecated in the future, but right now we have no plans of doing so.
171
217
218
+
### Model the SerialExecutor lifetime dependency on Actor using `~Escapable`
219
+
220
+
It is currently not possible to express this lifetime dependency using `~Escapable` types, because combining `any SerialExecutor` which is an `AnyObject` constrained type, cannot be combined with `~Escapable`. Perhaps in a future revision it would be possible to offer a non-escapable serial executor in order to model this using non-escapable types, rather than a `with`-style API.
221
+
172
222
## Changelog
173
223
224
+
- added way to obtain `SerialExecutor` from `Actor` in a safe, scoped, way. This enables using the `isIsolatingCurrentContext()` API when we have an `any Actor`, e.g. from an `@isolated(any)` closure.
174
225
- changed return value of `isIsolatingCurrentContext` from `Bool` to `Bool?`, where the `nil` is to be interpreted as "unknown", and the default implementation of `isIsolatingCurrentContext` now returns `nil`.
175
226
- removed the manual need to signal to the runtime that the specific executor supports the new checking mode. It is now detected by the compiler and runtime, checking for the presence of a non-default implementation of the protocol requirement.
0 commit comments