How Programming Languages Model Asynchronous Program Flow 34 The typical flow goes as follows: Y ou run some non-blocking code Y ou make a blocking call to some external resource The CPU jumps to the main thread, which schedules a different thread to run and jumps to that stack Y ou run some non-blocking code on the new thread until a new blocking call or the task is finished The CPU jumps back to the main thread, schedules a new thread that is ready to make progress, and jumps to that thread Figure 2. 2-Program flow using fibers/green threads Each stack has a fixed space As fibers and green threads are similar to OS threads, they do have some of the same drawbacks as well. Each task is set up with a stack of a fixed size, so you still have to reserve more space than you actually use. However, these stacks can be growable, meaning that once the stack is full, the runtime can grow the stack. While this sounds easy, it's a rather complicated problem to solve. We can't simply grow a stack as we grow a tree. What actually needs to happen is one of two things: 1. Y ou allocate a new piece of continuous memory and handle the fact that your stack is spread over two disjointed memory segments 2. Y ou allocate a new larger stack (for example, twice the size of the previous stack), move all your data over to the new stack, and continue from there 