1. Issues
The C++ Coroutine TS [N4736] has issues 31 and 32 listed in [P0664R5]:
31. Add a note warning about thread switching near await and/or
wording.coroutine_handle Add a note warning about thread switching near await and/or
wordingcoroutine_handle 32. Add a normative text making it UB to migrate coroutines between certain kind of execution agents.
Add a normative text making it UB to migrate coroutines between certain kind of execution agents. Clarify that migrating between
s is OK. But migrating between CPU and GPU is UB.std :: thread 
2. Discussion
Using 
thread :: id get_an_id () { // here: acquire a lock, read thread_local co_yield std :: this_thread :: get_id (); //< one result // UB: release the lock, reuse the same thread_local co_return std :: this_thread :: get_id (); //< different result } 
We say "teleport" here because the code that relocates the coroutine is outside the coroutine, in a possibly unrelated part of the program. This teleportation can take your coroutine to many interesting places, for example:
- 
     the thread that runs main 
- 
     threads from std :: thread std :: async 
- 
     elemental functions of std :: par std :: par_unseq std :: unseq 
- 
     global / thread_local 
- 
     global / thread_local static 
- 
     functions registered with at_exit quick_exit 
- 
     signal handlers 
- 
     future fibers_context 
Note that it is presently implementation-defined whether many of these functions run in a specific thread, a single thread, or in many unspecified threads—see [CWG2046].
3. Proposed Resolution
After [N4736] [dcl.fct.def.coroutine] ❡6:
A suspended coroutine can be resumed to continue execution by invoking a resumption member function of an object of type
associated with this instance of the coroutine. The function that invoked a resumption member function is called resumer. Invoking a resumption member function for a coroutine that is not suspended results in undefined behavior.coroutine_handle & lt ; P & gt ; 
Add ❡7:
Resuming a coroutine on an execution agent other than the one it was suspended on has implementation-defined behavior unless both are instances of
. [Note: a coroutine that is moved this way should avoid the use ofstd :: thread orthread_local objects. — End note.]mutex