Talk:cpp/language/coroutines
[edit] confusing definition about "the caller/resumer of the current coroutine"
In this page we talk about "the caller/resumer of the current coroutine", but it's not clear for me. In my testing, it should be the place where we call resume() or operator() of the coroutine_handle. Btw, in below description "if await_suspend returns a coroutine handle for some other coroutine, that handle is resumed", we may think other coroutine is resumed by await_suspend, the resumer talked above is await_suspend. We should clarify it. (Macomphy (talk) 20:39, 20 March 2023 (PDT))
[edit] Confusing await_suspend note
This sentence is very puzzling: Note that because the coroutine is fully suspended before entering awaiter.await_suspend(), that function is free to transfer the coroutine handle across threads, with no additional synchronization.
It's unclear what "additional synchronization" means here. And I can't find anything about implicit memory sequencing in the standard. So I assume that there still needs to be all the proper synchronization done by the await_suspend function so that the coroutine sees its own state while running another thread. It's just that the coroutine itself doesn't have to care about threads or synchronization.
- this refers to Synchronization-free async code from the Lewis Baker blog, to quote "For example, by starting an async-read operation inside await_suspend() when the coroutine is already suspended means that we can just resume the coroutine when the operation completes without needing any thread-synchronisation to coordinate the thread that started the operation and the thread that completed the operation." --Cubbi (talk) 12:05, 21 September 2021 (PDT)
- I don't think this is correct in general. It will work if the completion of the async read launches a new thread since then the thread is created after the subroutine was suspended. But if you just shift the subroutine between threads without synchronization, I don't see why the receiving thread would have visibility of the coroutine state. --HappyCerberus
[edit] Mentioning what "stackless" means
I think this revert https://en.cppreference.com/mwiki/index.php?title=cpp/language/coroutines&curid=18439&diff=111978&oldid=111959 makes the description more confusing, because it may not be clear to the reader what "stackless" exactly means. I propose that we keep some description, e.g. "(i.e. the whole state of the coroutine is stored on the heap or in another location)".
--P12 05:58, 13 August 2019 (PDT)
[edit] co_await I don't understand
I understand all the others. But co_await I just don't understand.
?type? f() { co_await x(); some_code() }
when is x() executed? and on which thread is it executed? is some_code() now executed on another thread? when does everything return to the same thread that f() has been executed?
With the read example, does the read() function need to return a special type? can I do
co_await fread(...)
I have used generators before and it's very simple concept to me to understand. co_await I just can't wrap my head around it. because co_await makes f a coroutine f cannot be called directly from main(). I would like some examples to connect the dots to a non-coroutine function, as I don't understand.
Thank you guys for explaining.
- yes, x() can be executed on another thread, and some_code() could run on some third thread. Nothing has to return to the same thread that started f(). As for awaiting on fread(), typically the thing you co_await returns a type that defines operator co_await, but yes you can technically co_await fread(...), if your coroutine's Promise type defines await_transform from size_t to something awaitable. It just would be surprising. --Cubbi (talk) 08:31, 20 February 2020 (PST)
[edit] hi guys . online compiler for page not working with coroutines of i press run
In file included from main.cpp:1: /usr/local/include/c++/10.2.0/coroutine:295:2: error: #error "the coroutine header requires -fcoroutines"
295 | #error "the coroutine header requires -fcoroutines" | ^Eggmanoid (talk) 22:59, 25 November 2020 (PST)
main.cpp: In function 'auto switch_to_new_thread(std::jthread&)': main.cpp:10:24: error: 'std::coroutine_handle' has not been declared
10 | void await_suspend(std::coroutine_handle<> h) { | ^~~
main.cpp:10:45: error: expected ',' or '...' before '<' token
10 | void await_suspend(std::coroutine_handle<> h) { | ^
main.cpp: In member function 'void switch_to_new_thread(std::jthread&)::awaitable::await_suspend(int)': main.cpp:14:27: error: 'h' was not declared in this scope
- It's OK — online compiler (presently the GCC v10.2) has incomplete support of coroutines. You may check the Example with more recent version i.e. here: wandbox.org - coroutine example - gcc head 11.0. It compiles and runs w/o error messages. )
[edit] Example possibly relying on undefined behavior
In the example under Execution, it seems that coroutine_handle is being instantiated with an incomplete type struct promise.
From 16.4.5.8 In particular, the effects are undefined in the following cases: ... If an incomplete type ([basic.types.general]) is used as a template argument when instantiating a template component or evaluating a concept, unless specifically allowed for that component.
I don't see any phrases explicitly allowing instantiation of std::coroutine_handle under support.coroutine. Isn't this undefined behavior?
- maybe we can drop/move that example out of the bullet point list that it breaks up with a screenful of code. It's intended to illustrate "may become dangling" part, but perhaps it can be simpler illustrated as done in Core Guidelines CP.53 (and we can just borrow those three lines of code, or link to it with no code) --Cubbi (talk) 08:22, 22 March 2022 (PDT)