odem-rs 0.3.0

Object-based Discrete-Event Modelling in Rust using async/await
Documentation
//! This example demonstrates chain-based synchronization using FIFO and LIFO
//! ordering for coordinating entities.
//!
//! A train picks up passengers at a source station and drops them off at a
//! destination. Passengers board in FIFO order (first to arrive boards first)
//! and disembark in LIFO order (last to board leaves first), showcasing how
//! `Chain` can model both queue and stack disciplines within the same
//! simulation.

use core::pin::pin;
use odem_rs::{
	prelude::*,
	sync::chain::Chain,
	tracing::{Level, debug},
};

// 1. Define the simulation configuration with two Chains.
#[derive(Config, Default)]
struct TrainSim {
	platform: Chain, // For passengers waiting to board.
	cabin: Chain,    // For passengers inside the train.
}

// 2. Define the Passenger behavior.
struct Passenger;
impl Behavior<TrainSim> for Passenger {
	type Output = ();

	async fn actions(&self, sim: &Sim<TrainSim>) {
		let TrainSim { platform, cabin } = sim.global();

		// Wait on the platform in FIFO order (a queue).
		// The first passenger to arrive will be the first to board.
		platform.fifo().await;
		debug!("entering cabin");
		sim.advance(1.0).await; // Simulate time to board.
		platform.notify_one(); // Signal for the next person.

		// Wait inside the cabin in LIFO order (a stack).
		// The last passenger to board will be the first to leave.
		cabin.lifo().await;
		debug!("leaving cabin");
		sim.advance(1.0).await; // Simulate time to leave.
		cabin.notify_one(); // Signal for the next person.
	}
}

struct Train;
impl Behavior<TrainSim> for Train {
	type Output = ();

	async fn actions(&self, sim: &Sim<TrainSim>) {
		let TrainSim { platform, cabin } = sim.global();

		sim.advance(1.0).await; // Drive to source station.
		debug!("arriving in source station");
		platform.notify_one(); // Signal passengers on platform.

		sim.advance(2.0).await; // Wait for them to embark.

		debug!("departing source station");
		sim.advance(1.0).await; // Drive to destination station.
		debug!("arriving at destination");

		cabin.notify_one(); // Signal passengers in cabin.
		sim.advance(2.0).await; // Wait for them to disembark.
	}
}

async fn train_sim(sim: &Sim<TrainSim>) {
	let passengers = pin!(Pool::dynamic().with(Agent::new));
	let train = pin!(Agent::new(Train));

	sim.activate(train);

	for _ in 0..2 {
		sim.activate(passengers.alloc(Passenger));
	}

	sim.advance(10.0).await;
}

fn main() {
	// Initialize the logging framework.
	tracing_subscriber::fmt()
		.with_max_level(Level::DEBUG)
		.with_target(false)
		.with_timer(model_time!("[{time}]"))
		.init();

	simulation(train_sim).expect("no deadlock should be possible");
}