Skip to content

Latest commit

 

History

History
62 lines (54 loc) · 1.76 KB

scalable-stack.md

File metadata and controls

62 lines (54 loc) · 1.76 KB
title date author
Scalable Stack Overview
2025-01-08 00:44:00 -0800
loongs-zhang

Scalable Stack Overview

Usage

use open_coroutine_core::co;
use open_coroutine_core::common::constants::CoroutineState;
use open_coroutine_core::coroutine::suspender::Suspender;
use open_coroutine_core::coroutine::Coroutine;

fn main() -> std::io::Result<()> {
    let mut co = co!(|_: &Suspender<(), i32>, ()| {
        fn recurse(i: u32, p: &mut [u8; 10240]) {
            // You can also use `maybe_grow` in thread.
            Coroutine::<(), i32, ()>::maybe_grow(|| {
                // Ensure the stack allocation isn't optimized away.
                unsafe { std::ptr::read_volatile(&p) };
                if i > 0 {
                    recurse(i - 1, &mut [0; 10240]);
                }
            })
            .expect("allocate stack failed")
        }
        // Use ~500KB of stack.
        recurse(50, &mut [0; 10240]);
    })?;
    assert_eq!(co.resume()?, CoroutineState::Complete(()));
    Ok(())
}

Why scalable stack?

The default stack size of coroutine is 128KB, which is sufficient for most scenarios, but there are still some scenarios that are not applicable, such as recursive algorithms. The scalable stack enables annotating fixed points in programs where the stack may want to grow larger. Spills over to the heap if the stack has hit its limit.

How it works

flowchart TD
    Cond1{In coroutine}
    Cond2{Approach the limit}
    Cond3{Is the first growing up?}
    C[Create a new stack]
    RC[Run code on current stack]
    RN1[Run code on new stack]
    maybe_grow --> Cond1
    Cond1 -- Yes --> Cond2
    Cond2 -- Yes --> C
    Cond2 -- No --> RC
    C --> RN1
    Cond1 -- No --> Cond3
    Cond3 -- Yes --> C
    Cond3 -- No --> Cond2
Loading