//! General purpose simulation library that provides the mechanisms such as: scheduler, state,
//! queues, etc.
//!
//! **NOTE**: This is all experimental right now.
//!
//! The key public types are [`State`], [`Scheduler`], [`Components`], and [`Simulation`].
//! These, along with user-defined simulation components (structs implementing the [`Component`] trait),
//! are the simulation building blocks.
//! Let's first explain each of the above, and then look at examples.
//!
//! # State
//!
//! A simulation must have the ability to mutate its state.
//! This functionality is fully delegated to the [`State`] struct.
//! It can store, remove, and modify values of arbitrary types `T: 'static`.
//! It also allows us to create queues that can be used to move data between components.
//!
//! ## Value Store
//!
//! [`State`] exposes several simple functions to insert, access, modify, and remove values.
//! Existing values are manipulated using special type-safe keys that are generated and
//! returned when inserting the values.
//!
//! ```
//! # use simrs::State;
//! let mut state = State::default();
//! let key = state.insert(7);
//! assert_eq!(state.remove(key), Some(7));
//! ```
//!
//! Note that the following will fail to compile because of incompatible types:
//!
//! ```compile_fail
//! # use simrs::State;
//! let mut state = State::default();
//! let int_key = state.insert(7);
//! let str_key = state.insert("str");
//! let v: i32 = state.get(str_key);
//! ```
//!
//! ## Queues
//!
//! Queues work very similar to storing values but have a different user-facing interface.
//! The access is also done through a key type. However, a different type [`QueueId`] is
//! used for clarity.
//!
//! ```
//! # use simrs::{State, Fifo, Queue};
//! let mut state = State::default();
//! let queue_id = state.add_queue(Fifo::default());
//! state.send(queue_id, 1);
//! assert_eq!(state.len(queue_id), 1);
//! assert_eq!(state.recv(queue_id), Some(1));
//! assert_eq!(state.recv(queue_id), None);
//! ```
//!
//! Additionally, a bounded queue is available, which will return an error if the size reached
//! the capacity.
//!
//! ```
//! # use simrs::{State, Fifo, Queue};
//! let mut state = State::default();
//! let queue_capacity = 1;
//! let queue_id = state.add_queue(Fifo::bounded(queue_capacity));
//! assert!(state.send(queue_id, 1).is_ok());
//! assert_eq!(state.len(queue_id), 1);
//! assert!(!state.send(queue_id, 2).is_ok());
//! assert_eq!(state.len(queue_id), 1);
//! ```
//!
//! # Components
//!
//! The [`Components`] structure is a container for all registered components.
//! Similarly to values and queues in the state, components are identified by [`ComponentId`].
//!
//! ```
//! # use simrs::{Components, Component, State, Scheduler, ComponentId};
//! struct SomeComponent {
//! // ...
//! }
//! #[derive(Debug)]
//! enum SomeEvent {
//! A,
//! B,
//! C,
//! }
//! # impl SomeComponent {
//! # fn new() -> Self {
//! # SomeComponent {}
//! # }
//! # }
//! impl Component for SomeComponent {
//! type Event = SomeEvent;
//! fn process_event(
//! &self,
//! self_id: ComponentId<Self::Event>,
//! event: &Self::Event,
//! scheduler: &mut Scheduler,
//! state: &mut State,
//! ) {
//! // Do some work...
//! }
//! }
//!
//! # fn main() {
//! let mut components = Components::default();
//! let component_id = components.add_component(SomeComponent::new());
//! # }
//! ```
//!
//! # Scheduler
//!
//! The scheduler's main functionality is to keep track of the simulation time and
//! the future events. Events are scheduled to run on a specific component at a specified
//! time interval. Because the events are type-erased, it's up to the component to
//! downcast the event. To make it easy, each component gets a blanket implementation
//! of an internal trait that does that automatically. It is all encapsulated in the
//! `Components` container, as shown in the below example:
//!
//! ```
//! # use simrs::{Components, Component, State, Scheduler, ComponentId};
//! # use std::time::Duration;
//! # struct SomeComponent {
//! # // ...
//! # }
//! # #[derive(Debug)]
//! # enum SomeEvent {
//! # A,
//! # B,
//! # C,
//! # }
//! # impl SomeComponent {
//! # fn new() -> Self {
//! # SomeComponent {}
//! # }
//! # }
//! # impl Component for SomeComponent {
//! # type Event = SomeEvent;
//! # fn process_event(
//! # &self,
//! # self_id: ComponentId<Self::Event>,
//! # event: &Self::Event,
//! # scheduler: &mut Scheduler,
//! # state: &mut State,
//! # ) {
//! # // Do some work...
//! # }
//! # }
//! # fn main() {
//! let mut components = Components::default();
//! let mut scheduler = Scheduler::default();
//! let mut state = State::default();
//! let component_id = components.add_component(SomeComponent::new());
//! scheduler.schedule(
//! Duration::from_secs(1), // schedule 1 second from now
//! component_id,
//! SomeEvent::A,
//! );
//! let event_entry = scheduler.pop().unwrap();
//! components.process_event_entry(event_entry, &mut scheduler, &mut state);
//! # }
//! ```
//!
//! # Simulation
//!
//! [`Simulation`] takes aggregates everything under one structure and provides some additional functions.
//! See the example below.
//!
//! # Example
//!
//! ```
//! # use simrs::{Simulation, State, Scheduler, Components, ComponentId, Component, QueueId, Key, Fifo, Executor};
//! # use std::time::Duration;
//!
//! #[derive(Debug)]
//! struct Product;
//!
//! struct Producer {
//! outgoing: QueueId<Fifo<Product>>,
//! consumer: ComponentId<ConsumerEvent>,
//! produced_count: Key<usize>,
//! }
//!
//! struct Consumer {
//! incoming: QueueId<Fifo<Product>>,
//! working_on: Key<Option<Product>>,
//! }
//!
//! #[derive(Debug)]
//! struct ProducerEvent;
//!
//! #[derive(Debug)]
//! enum ConsumerEvent {
//! Received,
//! Finished,
//! }
//!
//! impl Producer {
//! fn produce(&self) -> Product {
//! Product
//! }
//! fn interval(&self) -> Duration {
//! Duration::from_secs(1)
//! }
//! }
//!
//! impl Consumer {
//! fn interval(&self) -> Duration {
//! Duration::from_secs(1)
//! }
//! fn log(&self, product: Product) {
//! println!("{:?}", product)
//! }
//! }
//!
//! impl Component for Producer {
//! type Event = ProducerEvent;
//!
//! fn process_event(
//! &self,
//! self_id: ComponentId<ProducerEvent>,
//! _event: &ProducerEvent,
//! scheduler: &mut Scheduler,
//! state: &mut State,
//! ) {
//! let count = *state.get(self.produced_count).unwrap();
//! if count < 10 {
//! let _ = state.send(self.outgoing, self.produce());
//! scheduler.schedule(self.interval(), self_id, ProducerEvent);
//! scheduler.schedule(Duration::default(), self.consumer, ConsumerEvent::Received);
//! *state.get_mut(self.produced_count).unwrap() = count + 1;
//! }
//! }
//! }
//!
//! impl Component for Consumer {
//! type Event = ConsumerEvent;
//!
//! fn process_event(
//! &self,
//! self_id: ComponentId<ConsumerEvent>,
//! event: &ConsumerEvent,
//! scheduler: &mut Scheduler,
//! state: &mut State,
//! ) {
//! let busy = state.get(self.working_on).is_some();
//! match event {
//! ConsumerEvent::Received => {
//! if busy {
//! if let Some(product) = state.recv(self.incoming) {
//! state.get_mut(self.working_on).map(|w| *w = Some(product));
//! scheduler.schedule(self.interval(), self_id, ConsumerEvent::Finished);
//! }
//! }
//! }
//! ConsumerEvent::Finished => {
//! let product = state.get_mut(self.working_on).unwrap().take().unwrap();
//! self.log(product);
//! if state.len(self.incoming) > 0 {
//! scheduler.schedule(Duration::default(), self_id, ConsumerEvent::Received);
//! }
//! }
//! }
//! }
//! }
//!
//! fn main() {
//! let mut simulation = Simulation::default();
//! let queue = simulation.add_queue(Fifo::default());
//! let working_on = simulation.state.insert::<Option<Product>>(None);
//! let consumer = simulation.add_component(Consumer {
//! incoming: queue,
//! working_on,
//! });
//! let produced_count = simulation.state.insert(0_usize);
//! let producer = simulation.add_component(Producer {
//! outgoing: queue,
//! consumer,
//! produced_count,
//! });
//! simulation.schedule(Duration::new(0, 0), producer, ProducerEvent);
//! // simulation.schedule(Duration::new(0, 0), consumer, ProducerEvent);
//! // The above would fail with: ^^^^^^^^^^^^^ expected enum `ConsumerEvent`, found struct `ProducerEvent`
//! simulation.execute(Executor::unbound().side_effect(|sim| {
//! println!("{:?}", sim.scheduler.time());
//! }));
//! }
//! ```
use Cell;
use PhantomData;
use Rc;
use Duration;
type Clock = ;
pub use ;
pub use ;
pub use State;
pub use ;
pub use ;
static ID_COUNTER: AtomicUsize = new;
/// Simulation struct that puts different parts of the simulation together.
///
/// See the [crate-level documentation](index.html) for more information.
/// Defines a strongly typed key type.
key_type!;
key_type!;
key_type!;