2
0
mirror of https://github.com/boostorg/cobalt.git synced 2026-01-19 16:12:15 +00:00
Files
cobalt/doc/background/stackless.adoc
2024-12-20 09:01:26 +08:00

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.