Creating Our Own Fibers 112 When you start a process in most modern operating systems, the standard stack size is normally 8 MB, but it can be configured differently. This is enough for most programs, but it's up to the programmer to make sure we don't use more than we have. This is the cause of the dreaded stack overflow that most of us have experienced. However, when we can control the stacks ourselves, we can choose the size we want. 8 MB for each task is way more than we need when running simple functions in a web server, for example, so by reducing the stack size, we can have millions of fibers/green threads running on a machine. We run out of memory a lot sooner using stacks provided by the operating system. Anyway, we need to consider how to handle the stack size, and most production systems such as Boost. Coroutine or the one you find in Go will use either segmented stacks or growable stacks. We will make this simple for ourselves and use a fixed stack size going forward. Implementing our own fibers Before we start, I want to make sure you understand that the code we write is quite unsafe and is not a “best practice” when writing Rust. I want to try to make this as safe as possible without introducing a lot of unnecessary complexity, but there is no way to avoid the fact that there will be a lot of unsafe code in this example. We will also prioritize focusing on how this works and explain it as simply as possible, which will be enough of a challenge in and of itself, so the focus on best practices and safety will have to take the back seat on this one. Let's start off by creating a whole new project called c-fibers and removing the code in main. rs so we start with a blank sheet. Note Y ou will also find this example in the repository under the ch05/c-fibers folder. This example, as well as ch05/d-fibers-closure and ch05/e-fibers-windows, needs to be compiled using the nightly compiler since we use an unstable feature. Y ou can do this in one of two ways: Override the default toolchain for the entire directory you're in by writing rustup override set nightly (I personally prefer this option). Tell cargo to use the nightly toolchain every time you compile or run the program using cargo +nightly run. We'll create a simple runtime with a very simple scheduler. Our fibers will save/restore their state so they can be stopped and resumed at any point during execution. Each fiber will represent a task that we want to progress concurrently, and we simply create a new fiber for each task we want to run.