Seastar allows writing such code, by using a seastar::thread object which comes with its own stack.
The seastar::thread allocates a 128KB stack, and runs the given function until then it blocks on the call to a future's get() method. Outside a seastar::thread context, get() may only be called on a future which is already available. But inside a thread, calling get() on a future which is not yet available stops running the thread function, and schedules a continuation for this future, which continues to run the thread's function (on the same saved stack) when the future becomes available.
The above sentences are quoted from seastar tutorial, Does this mean that seastar::thread is a kind of stackful coroutine?
Yes, seastar::thread
and "stackful coroutines" are indeed very similar concepts.
Note that Seastar also supports stackless coroutines, using the new C++20 coroutines feature. This is now almost always preferable over stackful coroutines (seastar::thread
): stackless coroutines are lighter and are useful also in heavily concurrent operations (where a stack per waiter is a big waste), have nicer support in the C++ language. Stackless coroutines also cooperate better with future-based code - when you write a function assuming it is running in a seastar::thread
, i.e., using get()
on unready futures, you can only call this function from inside a seastar::thread
. In contrast, if you write a stackless coroutine with the new C++ syntax - you can call it from any future-based or coroutine-based code.