mirror of
https://github.com/boostorg/cobalt.git
synced 2026-01-19 16:12:15 +00:00
106 lines
2.1 KiB
Plaintext
106 lines
2.1 KiB
Plaintext
[#stackless]
|
|
== Stackless
|
|
|
|
C++20 coroutines are stackless, meaning they don't have their own stack.
|
|
|
|
A stack in C++ describes the callstack, i.e. all the function frames stacked.
|
|
A function frame is the memory a function needs to operate, i.e. a slice of memory
|
|
to store its variables and information such as the return address.
|
|
|
|
NOTE: The size of a function frame is known at compile time, but not outside the compile unit containing its definition.
|
|
|
|
[source, cpp]
|
|
----
|
|
|
|
int bar() {return 0;} // the deepest point of the stack
|
|
int foo() {return bar();}
|
|
|
|
int main()
|
|
{
|
|
return foo();
|
|
}
|
|
----
|
|
|
|
The call stack in the above example is:
|
|
|
|
[source]
|
|
----
|
|
main()
|
|
foo()
|
|
bar()
|
|
----
|
|
|
|
ifdef::generate-diagram[]
|
|
[mermaid, target=stackless1]
|
|
----
|
|
sequenceDiagram
|
|
main->>+foo: call
|
|
foo->>+bar: call
|
|
bar->>-foo: return
|
|
foo->>-main: return
|
|
----
|
|
endif::[]
|
|
|
|
ifndef::generate-diagram[]
|
|
image::stackless1.png[]
|
|
endif::[]
|
|
|
|
Coroutines can be implemented as stackful, which means that it allocates a fixes chunk of memory and stacks function frames similar to a thread.
|
|
C++20 coroutines are stackless, i.e. they only allocate their own frame and use the callers stack on resumption. Using our previous example:
|
|
|
|
[source,cpp]
|
|
----
|
|
fictional_eager_coro_type<int> example()
|
|
{
|
|
co_yield 0;
|
|
co_yield 1;
|
|
}
|
|
|
|
void nested_resume(fictional_eager_coro_type<int>& f)
|
|
{
|
|
f.resume();
|
|
}
|
|
|
|
int main()
|
|
{
|
|
auto f = example();
|
|
nested_resume(f);
|
|
f.reenter();
|
|
return 0;
|
|
}
|
|
----
|
|
|
|
This will yield a call stack similar to this:
|
|
|
|
[source]
|
|
----
|
|
main()
|
|
f$example()
|
|
nested_resume()
|
|
f$example()
|
|
f$example()
|
|
----
|
|
|
|
|
|
ifdef::generate-diagram[]
|
|
[mermaid, target=stackless2]
|
|
----
|
|
sequenceDiagram
|
|
participant main
|
|
participant nested_resume
|
|
main->>+example: create & call
|
|
example-->>main: co_yield
|
|
main->>+nested_resume: call
|
|
nested_resume-->>example: resume
|
|
example-->>nested_resume: co_yield
|
|
nested_resume->>-main: return
|
|
main-->>example: resume
|
|
example->>-main: co_return
|
|
----
|
|
endif::[]
|
|
|
|
ifndef::generate-diagram[]
|
|
image::stackless2.png[]
|
|
endif::[]
|
|
|
|
The same applies if a coroutine gets moved accross threads. |