@@ -210,8 +210,80 @@ including important milestones.
210
210
obsoleted: < #version number#>
211
211
```
212
212
The * version number* consists of one to three positive integers, separated by periods.
213
+
214
+ - The ` noasync ` argument indicates that
215
+ the declared symbol can't be used directly
216
+ in an asynchronous context.
217
+
218
+ Because Swift concurrency can resume on a different thread
219
+ after a potential suspension point,
220
+ using elements like thread-local storage, locks, mutexes, or semaphores
221
+ across suspension points can lead to incorrect results.
222
+
223
+ To avoid this problem,
224
+ add an ` @available(*, noasync) ` attribute to the symbol's declaration:
225
+
226
+ ``` swift
227
+ extension pthread_mutex_t {
228
+
229
+ @available (* , noasync )
230
+ mutating func lock () {
231
+ pthread_mutex_lock (& self )
232
+ }
233
+
234
+ @available (* , noasync )
235
+ mutating func unlock () {
236
+ pthread_mutex_unlock (& self )
237
+ }
238
+ }
239
+ ```
240
+
241
+ This attribute raises a compile-time error
242
+ when someone uses the symbol in an asynchronous context.
243
+ You can also use the ` message ` argument to provide additional information
244
+ about the symbol.
245
+
246
+ ``` swift
247
+ @available (* , noasync , message : " Migrate locks to Swift concurrency." )
248
+ mutating func lock () {
249
+ pthread_mutex_lock (& self )
250
+ }
251
+ ```
252
+
253
+ If you can guarantee that your code
254
+ uses a potentially unsafe symbol in a safe manner,
255
+ you can wrap it in a synchronous function and call that function
256
+ from an asynchronous context.
257
+
258
+ ``` swift
259
+
260
+ // Provide a synchronous wrapper around methods with a noasync declaration.
261
+ extension pthread_mutex_t {
262
+ mutating func withLock (_ operation : () -> ()) {
263
+ self .lock ()
264
+ operation ()
265
+ self .unlock ()
266
+ }
267
+ }
268
+
269
+ func downloadAndStore (key : Int ,
270
+ dataStore : MyKeyedStorage,
271
+ dataLock : inout pthread_mutex_t) async {
272
+ // Safely call the wrapper in an asynchronous context.
273
+ dataLock.withLock {
274
+ dataStore[key] = downloadContent ()
275
+ }
276
+ }
277
+ ```
278
+
279
+ You can use the ` noasync ` argument on most declarations;
280
+ however, you can't use it when declaring deinitializers.
281
+ Swift must be able to call a class's deinitializers from any context,
282
+ both synchronous and asynchronous.
283
+
213
284
- The ` message ` argument provides a textual message that the compiler displays
214
- when emitting a warning or error about the use of a deprecated or obsoleted declaration.
285
+ when emitting a warning or error about the use
286
+ of a declaration marked ` deprecated ` , ` obsoleted ` , or ` noasync ` .
215
287
It has the following form:
216
288
217
289
``` swift
0 commit comments