@@ -210,8 +210,105 @@ 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 the declared symbol can't be used directly
215
+ in an asynchronous context.
216
+
217
+ Because Swift concurrency can resume on a different thread
218
+ after a potential suspension point,
219
+ you can't use elements like thread-local storage, locks, mutexes, and semaphores
220
+ across suspension points. For example, accessing thread-local storage
221
+ on both sides of a suspension point could produce unintended behaviors.
222
+
223
+ ``` swift
224
+ let customThreadLog = " CustomThreadLog"
225
+
226
+ // Reads the log for the current thread.
227
+ func readLog () -> String ? {
228
+ return Thread.current .threadDictionary [customThreadLog] as? String
229
+ }
230
+
231
+ // Add text to the log for the current thread.
232
+ func appendToLog (_ text : String ) {
233
+ var log = readLog () ?? " "
234
+ log.append (text)
235
+ Thread.current .threadDictionary [customThreadLog] = log
236
+ }
237
+
238
+ // This function modifies thread-local storage across a
239
+ // potential suspension point.
240
+ func verify (name : String ) async {
241
+ // This call appends the text to the current thread's log.
242
+ appendToLog (" Verifying \( name ) .\n " )
243
+
244
+ // This is a potential suspension point.
245
+ let result = await coin.flip ()
246
+
247
+ // This call might append the text to a different thread's log.
248
+ appendToLog (" \( name ) \( result ? " is" : " isn't" ) verified!\n\n " )
249
+ }
250
+ ```
251
+
252
+ In the previous code listing,
253
+ the compiler doesn't have enough information to detect the problem.
254
+ To prevent issues like this,
255
+ add an ` @available(*, noasync) ` attribute to the symbol's declaration:
256
+
257
+ ``` swift
258
+ // Reads the name for the current thread.
259
+ @available (* , noasync )
260
+ func readLog () -> String ? {
261
+ return Thread.current .threadDictionary [customThreadLog] as? String
262
+ }
263
+ ```
264
+
265
+ This attribute tells the compiler to raise a build error
266
+ when the symbol is used in an asynchronous context.
267
+ You can also use the ` message ` attribute to provide additional information
268
+ about the symbol.
269
+
270
+ ``` swift
271
+ // Reads the name for the current thread.
272
+ @available (* , noasync , message : " Use safeVerify(name:) instead." )
273
+ func readLog () -> String ? {
274
+ return Thread.current .threadDictionary [customThreadLog] as? String
275
+ }
276
+ ```
277
+
278
+ While the ` noasync ` argument prevents accidental, unsafe use of a symbol,
279
+ it can also prevent safe uses.
280
+ In many cases, ` nonasync ` symbols can still be used safely in specific situations.
281
+ If you can ensure that a particular use is safe in an asynchronous context,
282
+ wrap the symbol in a safe, synchronous function.
283
+ You can then call that synchronous wrapper from your asynchronous context.
284
+ The compiler won't raise an error, because the ` noasync ` symbol
285
+ isn't used directly in an asynchronous context.
286
+
287
+ ``` swift
288
+ // A synchronous wrapper function around the noasync functions
289
+ // guarantees that there won't be a potential suspension point
290
+ // between the appendToLog() calls.
291
+ func safeVerify (name : String ) -> String {
292
+ appendToLog (" Verifying \( name ) .\n " )
293
+
294
+ // This is no longer a potential suspension point.
295
+ let result = coin.synchronousFlip ()
296
+
297
+ appendToLog (" \( name ) \( result ? " is" : " isn't" ) verified!\n\n " )
298
+
299
+ // Multiple calls to safeVerify() may not occur on the same thread.
300
+ // Return the log for the current thread.
301
+ return readLog () ?? " No log found."
302
+ }
303
+ ```
304
+
305
+ You can use the ` noasync ` argument with most declarations;
306
+ however, you can't use it when declaring destructors,
307
+ because the system must be able to call destructors from any context.
308
+
213
309
- 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.
310
+ when emitting a warning or error about the use of a deprecated, obsoleted,
311
+ or noasync declaration.
215
312
It has the following form:
216
313
217
314
``` swift
0 commit comments