Skip to content

Manifold

A Manifold is the long-lived, per-core state machine the runtime drives with completions straight from io_uring (or kqueue in dev) — the runtime is named after it. It’s mounted once and lives for the whole executor: instead of spawning machinery per request, you put durable per-core work — a listener, a database connection, a timer — in a manifold and let the executor feed it kernel events until the program exits.

core executor mount exit
task / request
dope · mounted once
Listener
Connector (db)
Timer
pub trait Manifold: Sized {
const ID: u8 = 0;
fn dispatch(
self: Pin<&mut Self>,
ev: backend::Event,
driver: &mut Driver,
);
fn idle(self: Pin<&Self>) -> Idle { Idle::Park(None) }
// pre_park, on_wake, on_shutdown …
}
  • Completions go straight from the kernel to the manifold — no queue between threads.
  • const ID routes through a generated match, not a vtable — the no-dyn feature in practice.
  • Pin<&mut Self> — manifolds are in-place machines, not values shuffled around.

Several manifolds compose through #[derive(Dispatcher)]:

#[derive(Dispatcher)]
struct App {
#[manifold] http: Listener</* … */>,
#[manifold] db: Connector</* … */>,
}

Each field is a concrete type; the derive generates dispatch and wake as match arms over the IDs. dope ships the common ones — listener, connector — so cartel and sark build straight on them.

For ordinary async / await, reach for the Fiber.