apsis-rs/crates/sim/apsis-sim-engine/src/lib.rs

54 lines
1.9 KiB
Rust

//! Discrete-event simulation engine.
//!
//! 离散事件仿真引擎。
//!
//! The engine advances a clock by jumping from one event to the next. It
//! holds the event queue, the current simulation time, and the statistics a
//! caller needs to judge a run. What an event means is the caller's: it
//! supplies a handler that receives the event and may schedule more events,
//! and the engine only sequences the calls.
//!
//! The engine keeps the simulation deterministic. Events at the same instant
//! are delivered in the order they were scheduled, which the event queue
//! guarantees, so a run with the same inputs produces the same output. That
//! is what makes a result reproducible and a cross-check against another
//! implementation meaningful.
//!
//! The engine stops for one of four reasons, reported as a
//! [`StopReason`]:
//! the queue empties, the simulation reaches its time limit, the caller asks
//! it to stop, or an event limit is reached. The last two exist so that a
//! model that schedules events forever cannot run without bound.
//!
//! ```
//! use apsis_sim_engine::Engine;
//!
//! let mut engine = Engine::new();
//! engine.schedule(10.0, "hello");
//!
//! let mut seen = Vec::new();
//! let outcome = engine.run(|engine, event| {
//! seen.push(event.payload);
//! // The handler schedules the next event, which the engine delivers
//! // after this one. It schedules it only once, so the queue drains.
//! if event.payload == "hello" {
//! engine.schedule(20.0, "world");
//! }
//! });
//!
//! assert_eq!(seen, vec!["hello", "world"]);
//! assert_eq!(outcome.executed, 2);
//! assert_eq!(engine.now(), 20.0);
//! ```
#![forbid(unsafe_code)]
#![deny(missing_docs)]
mod engine;
mod outcome;
pub use engine::Engine;
pub use outcome::{EngineOutcome, EngineState, StopReason};
pub use apsis_event::{Event, EventId, EventQueue, QueueState};