@@ -640,7 +640,8 @@ tasks, and can have explicit *suspend points* where they suspend execution.
640
640
otherwise can be invoked with the normal ``apply `` and ``try_apply ``
641
641
instructions (or ``begin_apply `` if they are coroutines).
642
642
643
- ``@async `` functions may express primitive suspend points by using the
643
+ In Swift, the ``withUnsafeContinuation `` primitive is used to implement
644
+ primitive suspend points. In SIL, ``@async `` functions represent this abstraction
644
645
``begin_async_continuation[_addr] `` and ``await_async_continuation ``
645
646
instructions. ``begin_async_continuation[_addr] `` creates a *continuation *
646
647
value that can be used to resume the coroutine when it suspends, feeding a
@@ -649,10 +650,49 @@ error when it resumes. The resulting continuation value can then be passed
649
650
into a completion handler, registered with an event loop, or scheduled by
650
651
some other mechanism. The ``await_async_continuation `` instruction suspends
651
652
execution of the coroutine until the continuation is invoked to resume it.
652
- All continuation values must be used to resume the async coroutine exactly
653
- once. It is undefined behavior to attempt to resume the same continuation
654
- more than once. Failing to resume a continuation will leave the coroutine
655
- stuck in the suspended state, leaking any memory or other resources it owns.
653
+ A use of ``withUnsafeContinuation `` in Swift::
654
+
655
+ func waitForCallback() async -> Int {
656
+ return await withUnsafeContinuation { cc in
657
+ registerCallback { cc.resume($0) }
658
+ }
659
+ }
660
+
661
+ might lower to the following SIL::
662
+
663
+ sil @waitForCallback : $@convention(thin) @async () -> Int {
664
+ entry:
665
+ %cc = begin_async_continuation $Int
666
+ %closure = function_ref @waitForCallback_closure
667
+ : $@convention(thin) (UnsafeContinuation<Int>) -> ()
668
+ apply %closure(%cc)
669
+ await_async_continuation %cc, resume resume_cc
670
+
671
+ resume_cc(%result : $Int):
672
+ return %result
673
+ }
674
+
675
+ The closure may then be inlined into the ``waitForCallback `` function::
676
+
677
+ sil @waitForCallback : $@convention(thin) @async () -> Int {
678
+ entry:
679
+ %cc = begin_async_continuation $Int
680
+ %registerCallback = function_ref @registerCallback
681
+ : $@convention(thin) (@convention(thick) () -> ()) -> ()
682
+ %callback_fn = function_ref @waitForCallback_callback
683
+ %callback = partial_apply %callback_fn(%cc)
684
+ apply %registerCallback(%callback)
685
+ await_async_continuation %cc, resume resume_cc
686
+
687
+ resume_cc(%result : $Int):
688
+ return %result
689
+ }
690
+
691
+ Every continuation value must be used exactly once to resume its associated
692
+ async coroutine once. It is undefined behavior to attempt to resume the same
693
+ continuation more than once. On the flip side, failing to resume a continuation
694
+ will leave the async task stuck in the suspended state, leaking any memory or
695
+ other resources it owns.
656
696
657
697
Coroutine Types
658
698
```````````````
0 commit comments