Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Order systems with channels

Access conflicts order systems that touch the same components. When two systems touch different components but one must still run after the other — B consumes an effect A produced — express that ordering with a channel.

Channel IDs

A channel is identified by a ChannelID. Model resources own these; they are not created directly. An environment key, a message handle, and a space handle each own a channel, and a model can register dedicated phase keys used only for ordering. Read the id from the resource, for example key.channel_id() or handle.channel_id().

Declaring produce and consume

A system declares channels through its AccessSets: insert a channel id into produces or consumes. Build the access set explicitly and construct the system with FnSystem::new:

let mut access = AccessSets::default();
access.read.set(firm_id);
access.write.set(bank_id);
access.produces.insert(phases.credit_cleared.channel_id());

let system = FnSystem::new(id, "credit_market", access, move |ecs| {
    // ...
    Ok(())
});

A later system that must run after it consumes the same channel:

let mut access = AccessSets::default();
access.read.set(bank_id);
access.consumes.insert(phases.credit_cleared.channel_id());

The scheduler places every consumer of a channel in a stage after all of its producers. Systems that neither produce nor consume the channel are unaffected and may still parallelise with either side.

Ordering whole phases

To sequence phases of a tick — "aggregate, then set targets, then run the labour market" — give each phase a channel: the phase's systems produce it, and the next phase's systems consume it. The macroeconomy example orders its quarterly schedule this way; see examples/macroeconomy/systems.rs.

Deriving component access and adding channels

FnSystem::from_queries derives component access from queries but does not add channels. When a system needs both, build an AccessSets (setting the component reads and writes, or deriving them), insert the channels, and use FnSystem::new.