pub struct SimulationContext { /* private fields */ }
Expand description
A facade for accessing the simulation state and producing events from simulation components.
Implementations§
Source§impl SimulationContext
impl SimulationContext
Sourcepub fn id(&self) -> Id
pub fn id(&self) -> Id
Returns the identifier of component associated with this context.
§Examples
use simcore::{Simulation, SimulationContext};
let mut sim = Simulation::new(123);
let comp_ctx = sim.create_context("comp");
let comp_id = comp_ctx.id();
assert_eq!(comp_id, 0); // component ids are assigned sequentially starting from 0
Sourcepub fn name(&self) -> &str
pub fn name(&self) -> &str
Returns the name of component associated with this context.
§Examples
use simcore::{Simulation, SimulationContext};
let mut sim = Simulation::new(123);
let comp_ctx = sim.create_context("comp");
let comp_name = comp_ctx.name();
assert_eq!(comp_name, "comp");
Sourcepub fn time(&self) -> f64
pub fn time(&self) -> f64
Returns the current simulation time.
§Examples
use simcore::{Simulation, SimulationContext};
let mut sim = Simulation::new(123);
let comp_ctx = sim.create_context("comp");
let time = comp_ctx.time();
assert_eq!(time, 0.0);
Sourcepub fn rand(&self) -> f64
pub fn rand(&self) -> f64
Returns a random float in the range [0, 1) using the simulation-wide random number generator.
§Examples
use simcore::{Simulation, SimulationContext};
let mut sim = Simulation::new(123);
let mut comp_ctx = sim.create_context("comp");
let f: f64 = comp_ctx.rand();
assert!(f >= 0.0 && f < 1.0);
Sourcepub fn gen_range<T, R>(&self, range: R) -> Twhere
T: SampleUniform,
R: SampleRange<T>,
pub fn gen_range<T, R>(&self, range: R) -> Twhere
T: SampleUniform,
R: SampleRange<T>,
Returns a random number in the specified range using the simulation-wide random number generator.
§Examples
use simcore::{Simulation, SimulationContext};
let mut sim = Simulation::new(123);
let mut comp_ctx = sim.create_context("comp");
let n: u32 = comp_ctx.gen_range(1..=10);
assert!(n >= 1 && n <= 10);
let f: f64 = comp_ctx.gen_range(0.1..0.5);
assert!(f >= 0.1 && f < 0.5);
Sourcepub fn sample_from_distribution<T, Dist: Distribution<T>>(
&self,
dist: &Dist,
) -> T
pub fn sample_from_distribution<T, Dist: Distribution<T>>( &self, dist: &Dist, ) -> T
Returns a random value from the specified distribution using the simulation-wide random number generator.
Sourcepub fn random_string(&self, len: usize) -> String
pub fn random_string(&self, len: usize) -> String
Returns a random alphanumeric string of specified length using the simulation-wide random number generator.
Sourcepub fn emit<T>(&self, data: T, dst: Id, delay: f64) -> EventIdwhere
T: EventData,
pub fn emit<T>(&self, data: T, dst: Id, delay: f64) -> EventIdwhere
T: EventData,
Creates new event with specified payload, destination and delay, returns event id.
The event time will be current_time + delay
.
It is not allowed to create events before the current simulation time, so delay
should be non-negative.
The event source will be equal to id
.
See emit_as
if you want to emit event on behalf of some other component.
§Examples
use std::cell::RefCell;
use std::rc::Rc;
use serde::Serialize;
use simcore::{cast, Event, EventHandler, Simulation, SimulationContext};
#[derive(Clone, Serialize)]
struct SomeEvent {
some_field: u32,
}
struct Component {
ctx: SimulationContext,
}
impl EventHandler for Component {
fn on(&mut self, event: Event) {
cast!(match event.data {
SomeEvent { some_field } => {
assert_eq!(self.ctx.time(), 1.2);
assert_eq!(event.time, 1.2);
assert_eq!(event.id, 0);
assert_eq!(some_field, 16);
}
})
}
}
let mut sim = Simulation::new(123);
let mut comp1_ctx = sim.create_context("comp1");
let mut comp2_ctx = sim.create_context("comp2");
let comp2_id = sim.add_handler("comp2", Rc::new(RefCell::new(Component { ctx: comp2_ctx })));
let event_id = comp1_ctx.emit(SomeEvent{ some_field: 16 }, comp2_id, 1.2);
assert_eq!(event_id, 0); // events ids are assigned sequentially starting from 0
sim.step();
assert_eq!(sim.time(), 1.2);
use serde::Serialize;
use simcore::{Simulation, SimulationContext};
#[derive(Clone, Serialize)]
struct SomeEvent {
}
let mut sim = Simulation::new(123);
let mut comp1_ctx = sim.create_context("comp1");
let mut comp2_ctx = sim.create_context("comp2");
comp1_ctx.emit(SomeEvent{}, comp2_ctx.id(), -1.0); // will panic because of negative delay
Sourcepub fn emit_ordered<T>(&self, data: T, dst: Id, delay: f64) -> EventIdwhere
T: EventData,
pub fn emit_ordered<T>(&self, data: T, dst: Id, delay: f64) -> EventIdwhere
T: EventData,
This and all other emit_ordered...
functions are special variants of normal emit_...
functions
that allow adding events to ordered event deque instead of heap, which may improve simulation performance.
Ordered events should be emitted in non-decreasing order of their time, otherwise the simulation will panic.
§Examples
use serde::Serialize;
use simcore::{Simulation, SimulationContext};
#[derive(Clone, Serialize)]
struct SomeEvent {
}
let mut sim = Simulation::new(123);
let mut comp1_ctx = sim.create_context("comp1");
let mut comp2_ctx = sim.create_context("comp2");
comp1_ctx.emit_ordered(SomeEvent{}, comp2_ctx.id(), 1.0);
comp1_ctx.emit_ordered(SomeEvent{}, comp2_ctx.id(), 1.0);
comp1_ctx.emit_ordered(SomeEvent{}, comp2_ctx.id(), 2.0);
sim.step();
assert_eq!(sim.time(), 1.0);
sim.step();
assert_eq!(sim.time(), 1.0);
sim.step();
assert_eq!(sim.time(), 2.0);
use serde::Serialize;
use simcore::{Simulation, SimulationContext};
#[derive(Clone, Serialize)]
struct SomeEvent {
}
let mut sim = Simulation::new(123);
let mut comp1_ctx = sim.create_context("comp1");
let mut comp2_ctx = sim.create_context("comp2");
comp1_ctx.emit_ordered(SomeEvent{}, comp2_ctx.id(), 2.0);
comp1_ctx.emit_ordered(SomeEvent{}, comp2_ctx.id(), 1.0); // will panic because of broken time order
Sourcepub fn can_emit_ordered(&self, delay: f64) -> bool
pub fn can_emit_ordered(&self, delay: f64) -> bool
Checks whether it is safe to emit an ordered event with the specified delay.
The time of new event must be not less than the time of the previously emitted ordered event.
Returns true if this condition holds and false otherwise.
§Examples
use serde::Serialize;
use simcore::{Simulation, SimulationContext};
#[derive(Clone, Serialize)]
struct SomeEvent {
}
let mut sim = Simulation::new(123);
let mut comp1_ctx = sim.create_context("comp1");
let mut comp2_ctx = sim.create_context("comp2");
comp1_ctx.emit_ordered(SomeEvent{}, comp2_ctx.id(), 1.0);
assert!(comp1_ctx.can_emit_ordered(1.0)); // 1.0 == 1.0
assert!(comp1_ctx.can_emit_ordered(1.1)); // 1.1 > 1.0
assert!(!comp1_ctx.can_emit_ordered(0.9)); // 0.9 < 1.0
comp1_ctx.emit_ordered(SomeEvent{}, comp2_ctx.id(), 1.5);
assert!(!comp1_ctx.can_emit_ordered(1.0)); // 1.0 < 1.5
sim.step();
assert_eq!(sim.time(), 1.0);
assert!(comp1_ctx.can_emit_ordered(1.0)); // 2.0 > 1.5
assert!(!comp1_ctx.can_emit_ordered(0.3)); // 1.3 < 1.5
Sourcepub fn emit_now<T>(&self, data: T, dst: Id) -> EventIdwhere
T: EventData,
pub fn emit_now<T>(&self, data: T, dst: Id) -> EventIdwhere
T: EventData,
Creates new immediate (zero-delay) event with specified payload and destination, returns event id.
This is a shorthand for emit
with zero delay.
§Examples
use std::cell::RefCell;
use std::rc::Rc;
use serde::Serialize;
use simcore::{cast, Event, EventHandler, Simulation, SimulationContext};
#[derive(Clone, Serialize)]
struct SomeEvent {
some_field: u32,
}
struct Component {
ctx: SimulationContext,
}
impl EventHandler for Component {
fn on(&mut self, event: Event) {
cast!(match event.data {
SomeEvent { some_field } => {
assert_eq!(self.ctx.time(), 0.0);
assert_eq!(event.time, 0.0);
assert_eq!(event.id, 0);
assert_eq!(some_field, 16);
}
})
}
}
let mut sim = Simulation::new(123);
let mut comp1_ctx = sim.create_context("comp1");
let mut comp2_ctx = sim.create_context("comp2");
let comp2_id = sim.add_handler("comp2", Rc::new(RefCell::new(Component { ctx: comp2_ctx })));
let event_id = comp1_ctx.emit_now(SomeEvent{ some_field: 16 }, comp2_id);
assert_eq!(event_id, 0); // events ids are assigned sequentially starting from 0
sim.step();
assert_eq!(sim.time(), 0.0);
Sourcepub fn emit_ordered_now<T>(&self, data: T, dst: Id) -> EventIdwhere
T: EventData,
pub fn emit_ordered_now<T>(&self, data: T, dst: Id) -> EventIdwhere
T: EventData,
See emit_ordered
.
Sourcepub fn emit_self<T>(&self, data: T, delay: f64) -> EventIdwhere
T: EventData,
pub fn emit_self<T>(&self, data: T, delay: f64) -> EventIdwhere
T: EventData,
Creates new event for itself with specified payload and delay, returns event id.
This is a shorthand for emit
with event destination equals id
.
§Examples
use std::cell::RefCell;
use std::rc::Rc;
use serde::Serialize;
use simcore::{cast, Event, EventHandler, Simulation, SimulationContext};
#[derive(Clone, Serialize)]
struct SomeEvent {
some_field: u32,
}
struct Component {
ctx: SimulationContext,
}
impl Component {
fn start(&mut self) {
self.ctx.emit_self(SomeEvent{ some_field: 16 }, 6.4);
}
}
impl EventHandler for Component {
fn on(&mut self, event: Event) {
cast!(match event.data {
SomeEvent { some_field } => {
assert_eq!(self.ctx.time(), 6.4);
assert_eq!(event.time, 6.4);
assert_eq!(event.id, 0);
assert_eq!(event.src, self.ctx.id());
assert_eq!(some_field, 16);
}
})
}
}
let mut sim = Simulation::new(123);
let comp1 = Rc::new(RefCell::new(Component { ctx: sim.create_context("comp1") }));
let comp1_id = sim.add_handler("comp1", comp1.clone());
comp1.borrow_mut().start();
sim.step();
assert_eq!(sim.time(), 6.4);
Sourcepub fn emit_ordered_self<T>(&self, data: T, delay: f64) -> EventIdwhere
T: EventData,
pub fn emit_ordered_self<T>(&self, data: T, delay: f64) -> EventIdwhere
T: EventData,
See Self::emit_ordered
.
Sourcepub fn emit_self_now<T>(&self, data: T) -> EventIdwhere
T: EventData,
pub fn emit_self_now<T>(&self, data: T) -> EventIdwhere
T: EventData,
Creates new immediate event for itself with specified payload, returns event id.
This is a shorthand for emit
with event destination equals id
and zero delay.
§Examples
use std::cell::RefCell;
use std::rc::Rc;
use serde::Serialize;
use simcore::{cast, Event, EventHandler, Simulation, SimulationContext};
#[derive(Clone, Serialize)]
struct SomeEvent {
some_field: u32,
}
struct Component {
ctx: SimulationContext,
}
impl Component {
fn start(&mut self) {
self.ctx.emit_self_now(SomeEvent{ some_field: 16 });
}
}
impl EventHandler for Component {
fn on(&mut self, event: Event) {
cast!(match event.data {
SomeEvent { some_field } => {
assert_eq!(self.ctx.time(), 0.0);
assert_eq!(event.time, 0.0);
assert_eq!(event.id, 0);
assert_eq!(event.src, self.ctx.id());
assert_eq!(some_field, 16);
}
})
}
}
let mut sim = Simulation::new(123);
let comp1 = Rc::new(RefCell::new(Component { ctx: sim.create_context("comp1") }));
let comp1_id = sim.add_handler("comp1", comp1.clone());
comp1.borrow_mut().start();
sim.step();
assert_eq!(sim.time(), 0.0);
Sourcepub fn emit_ordered_self_now<T>(&self, data: T) -> EventIdwhere
T: EventData,
pub fn emit_ordered_self_now<T>(&self, data: T) -> EventIdwhere
T: EventData,
See emit_ordered
.
Sourcepub fn emit_as<T>(&self, data: T, src: Id, dst: Id, delay: f64) -> EventIdwhere
T: EventData,
pub fn emit_as<T>(&self, data: T, src: Id, dst: Id, delay: f64) -> EventIdwhere
T: EventData,
Creates new event with specified payload, source, destination and delay, returns event id.
This is an extended version of emit
for special cases when the event should be emitted
on behalf of another component.
use std::cell::RefCell;
use std::rc::Rc;
use serde::Serialize;
use simcore::{cast, Event, EventHandler, Simulation, SimulationContext};
#[derive(Clone, Serialize)]
struct SomeEvent {
some_field: u32,
}
struct Component {
ctx: SimulationContext,
}
impl EventHandler for Component {
fn on(&mut self, event: Event) {
cast!(match event.data {
SomeEvent { some_field } => {
assert_eq!(self.ctx.time(), 2.4);
assert_eq!(event.time, 2.4);
assert_eq!(event.id, 0);
assert_eq!(event.src, 0);
assert_eq!(self.ctx.id(), 1);
assert_eq!(some_field, 8);
}
})
}
}
let mut sim = Simulation::new(123);
let comp1 = Rc::new(RefCell::new(Component { ctx: sim.create_context("comp1") }));
let comp1_id = sim.add_handler("comp1", comp1);
let comp2 = Rc::new(RefCell::new(Component { ctx: sim.create_context("comp2") }));
let comp2_id = sim.add_handler("comp2", comp2);
let mut other_ctx = sim.create_context("other");
other_ctx.emit_as(SomeEvent{ some_field: 8 }, comp1_id, comp2_id, 2.4);
sim.step();
assert_eq!(sim.time(), 2.4);
Sourcepub fn emit_ordered_as<T>(
&self,
data: T,
src: Id,
dst: Id,
delay: f64,
) -> EventIdwhere
T: EventData,
pub fn emit_ordered_as<T>(
&self,
data: T,
src: Id,
dst: Id,
delay: f64,
) -> EventIdwhere
T: EventData,
See emit_ordered
.
Sourcepub fn cancel_event(&self, id: EventId)
pub fn cancel_event(&self, id: EventId)
Cancels the specified event.
Use EventId
obtained when creating the event to cancel it.
Note that already processed events cannot be cancelled.
§Examples
use serde::Serialize;
use simcore::{Simulation, SimulationContext};
#[derive(Clone, Serialize)]
struct SomeEvent {
}
let mut sim = Simulation::new(123);
let mut comp1_ctx = sim.create_context("comp1");
let mut comp2_ctx = sim.create_context("comp2");
let event1 = comp1_ctx.emit(SomeEvent{}, comp2_ctx.id(), 1.0);
let event2 = comp1_ctx.emit(SomeEvent{}, comp2_ctx.id(), 2.0);
sim.step();
comp1_ctx.cancel_event(event2);
sim.step_until_no_events();
assert_eq!(sim.time(), 1.0);
Sourcepub fn cancel_events<F>(&self, pred: F)
pub fn cancel_events<F>(&self, pred: F)
Cancels events that satisfy the given predicate function.
Note that already processed events cannot be cancelled.
§Examples
use serde::Serialize;
use simcore::{Event, Simulation, SimulationContext};
#[derive(Clone, Serialize)]
struct SomeEvent {
}
let mut sim = Simulation::new(123);
let mut comp1_ctx = sim.create_context("comp1");
let mut comp2_ctx = sim.create_context("comp2");
let event1 = comp1_ctx.emit(SomeEvent{}, comp2_ctx.id(), 1.0);
let event2 = comp1_ctx.emit(SomeEvent{}, comp2_ctx.id(), 2.0);
let event2 = comp1_ctx.emit(SomeEvent{}, comp2_ctx.id(), 3.0);
comp1_ctx.cancel_events(|e| e.id < 2);
sim.step();
assert_eq!(sim.time(), 3.0);
Sourcepub fn cancel_heap_events<F>(&self, pred: F)
pub fn cancel_heap_events<F>(&self, pred: F)
Same as cancel_events
, but ignores events added through emit_ordered_...
methods.
Sourcepub fn lookup_name(&self, id: Id) -> String
pub fn lookup_name(&self, id: Id) -> String
Returns component name by its identifier.
§Examples
use std::cell::RefCell;
use std::rc::Rc;
use serde::Serialize;
use simcore::{cast, Event, EventHandler, Simulation, SimulationContext};
#[derive(Clone, Serialize)]
struct SomeEvent {
}
struct Component {
ctx: SimulationContext,
}
impl EventHandler for Component {
fn on(&mut self, event: Event) {
cast!(match event.data {
SomeEvent { } => {
// look up the name of event source
let src_name = self.ctx.lookup_name(event.src);
assert_eq!(src_name, "comp1");
}
})
}
}
let mut sim = Simulation::new(123);
let mut comp1_ctx = sim.create_context("comp1");
let mut comp2_ctx = sim.create_context("comp2");
let comp2_id = sim.add_handler("comp2", Rc::new(RefCell::new(Component { ctx: comp2_ctx })));
comp1_ctx.emit(SomeEvent{}, comp2_id, 1.0);
sim.step();
Sourcepub fn spawn(&self, future: impl Future<Output = ()> + 'static)
Available on crate feature async_mode
only.
pub fn spawn(&self, future: impl Future<Output = ()> + 'static)
async_mode
only.Spawns a new asynchronous task for component associated with this context.
Passing component’s state to asynchronous tasks can be achieved by using Rc<Self>
instead of &self
reference.
Mutating the component’s state by asynchronous tasks can be achieved by wrapping this state into RefCell<_>
.
In order to spawn asynchronous tasks, component is required to be registered
as StaticEventHandler
. See the examples below.
§Examples
use std::rc::Rc;
use serde::Serialize;
use simcore::{cast, Simulation, SimulationContext, Event, StaticEventHandler};
#[derive(Clone, Serialize)]
struct Start {
tasks: u32,
}
struct Component {
ctx: SimulationContext,
}
impl Component {
fn on_start(self: Rc<Self>, tasks: u32) {
for i in 1..=tasks {
self.ctx.spawn(self.clone().step_waiting(i));
}
}
async fn step_waiting(self: Rc<Self>, num_steps: u32) {
for _ in 0..num_steps {
self.ctx.sleep(1.).await;
}
}
}
impl StaticEventHandler for Component {
fn on(self: Rc<Self>, event: Event) {
cast!(match event.data {
Start { tasks } => {
self.on_start(tasks);
}
})
}
}
let mut sim = Simulation::new(123);
let comp_ctx = sim.create_context("comp");
let comp_id = sim.add_static_handler("comp", Rc::new(Component {ctx: comp_ctx }));
let root_ctx = sim.create_context("root");
root_ctx.emit(Start { tasks: 10 }, comp_id, 10.);
sim.step_until_no_events();
assert_eq!(sim.time(), 20.);
use std::rc::Rc;
use simcore::{Simulation, SimulationContext};
struct Component {
ctx: SimulationContext,
}
impl Component {
fn start(self: Rc<Self>, tasks: u32) {
for i in 1..=tasks {
self.ctx.spawn(self.clone().step_waiting(i));
}
}
async fn step_waiting(self: Rc<Self>, num_steps: u32) {
for _i in 0..num_steps {
self.ctx.sleep(1.).await;
}
}
}
let mut sim = Simulation::new(123);
let mut comp = Rc::new(Component { ctx: sim.create_context("comp") });
// Panics because spawning async tasks for component without event handler is prohibited
// due to safety reasons.
// Register Component via Simulation::add_static_handler as in the previous example.
comp.start(10);
use std::rc::Rc;
use std::cell::RefCell;
use simcore::{Simulation, SimulationContext, Event, EventHandler};
struct Component {
ctx: SimulationContext,
counter: u32,
}
impl Component {
fn on_start(&mut self, tasks: u32) {
for i in 1..=tasks {
// Compile fails because reference to self is used in the async task,
// which is not allowed because of 'static requirements on the spawned future.
// 1. To spawn 'static futures register this component as StaticEventHandler.
// 2. Use RefCell to wrap the mutable state and access it in the async task via RefCell::borrow_mut.
// See the next example for details.
self.ctx.spawn(self.increase_counter(i));
}
}
async fn increase_counter(&mut self, num_steps: u32) {
for _ in 0..num_steps {
self.ctx.sleep(1.).await;
self.counter += 1;
}
}
}
impl EventHandler for Component {
fn on(&mut self, event: Event) {}
}
let mut sim = Simulation::new(123);
let comp_ctx = sim.create_context("comp");
let comp = Rc::new(RefCell::new(Component {ctx: comp_ctx, counter: 0 }));
sim.add_handler("comp", comp.clone());
comp.borrow_mut().on_start(10);
sim.step_until_no_events();
use std::rc::Rc;
use std::cell::RefCell;
use simcore::{Simulation, SimulationContext, Event, StaticEventHandler};
struct Component {
ctx: SimulationContext,
counter: RefCell<u32>,
}
impl Component {
fn on_start(self: Rc<Self>, tasks: u32) {
for i in 1..=tasks {
self.ctx.spawn(self.clone().increase_counter(i));
}
}
async fn increase_counter(self: Rc<Self>, num_steps: u32) {
for _ in 0..num_steps {
self.ctx.sleep(1.).await;
*self.counter.borrow_mut() += 1;
}
}
}
impl StaticEventHandler for Component {
fn on(self: Rc<Self>, event: Event) {}
}
let mut sim = Simulation::new(123);
let comp_ctx = sim.create_context("comp");
let comp = Rc::new(Component {ctx: comp_ctx, counter: RefCell::new(0) });
sim.add_static_handler("comp", comp.clone());
comp.clone().on_start(10);
sim.step_until_no_events();
assert_eq!(sim.time(), 10.);
// 1 + 2 + 3 + ... + 10 = 55
assert_eq!(*comp.counter.borrow(), 55);
Sourcepub fn sleep(&self, duration: f64) -> TimerFuture ⓘ
Available on crate feature async_mode
only.
pub fn sleep(&self, duration: f64) -> TimerFuture ⓘ
async_mode
only.Waits (asynchronously) until duration
seconds have elapsed.
§Examples
use futures::{stream::FuturesUnordered, StreamExt};
use simcore::Simulation;
let mut sim = Simulation::new(123);
let ctx = sim.create_context("comp");
sim.spawn(async move {
let initial_time = ctx.time();
ctx.sleep(5.).await;
let mut expected_time = initial_time + 5.;
assert_eq!(expected_time, ctx.time());
let mut futures = FuturesUnordered::new();
for i in 1..=10 {
futures.push(ctx.sleep(i as f64));
}
while let Some(_) = futures.next().await {
expected_time += 1.;
assert_eq!(expected_time, ctx.time());
}
});
sim.step_until_no_events();
assert_eq!(15., sim.time());
Sourcepub async fn yield_now(&self)
Available on crate feature async_mode
only.
pub async fn yield_now(&self)
async_mode
only.Waits (asynchronously) until all events scheduled at the current time are processed.
May be useful to execute some logic without a time delay but after all events have been processed.
If there are several yield_now
calls at the same simulation time, the order of their completion
is the same as the order of the calls.
§Examples
use std::cell::RefCell;
use serde::Serialize;
use simcore::Simulation;
#[derive(Clone, Serialize)]
struct Request {}
#[derive(Clone, Serialize)]
struct Response {}
let mut sim = Simulation::new(123);
let master = sim.create_context("master");
let worker_1 = sim.create_context("worker_1");
let worker_2 = sim.create_context("worker_2");
sim.spawn(async move {
let mut counter = RefCell::new(0);
futures::join!(
async {
master.emit(Request {}, worker_1.id(), 5.);
master.recv_event::<Response>().await;
// Wait until workers exchange 3 messages.
master.yield_now().await;
assert_eq!(*counter.borrow(), 3);
assert_eq!(master.time(), 5.);
master.sleep(5.).await;
},
async {
worker_1.recv_event::<Request>().await;
worker_1.emit_now(Response {}, master.id());
for _ in 0..3 {
worker_1.emit_now(Request {}, worker_2.id());
}
for _ in 0..3 {
worker_1.recv_event::<Response>().await;
*counter.borrow_mut() += 1;
}
},
async {
loop {
let request = worker_2.recv_event::<Request>().await;
worker_2.emit_now(Response {}, request.src);
}
}
);
});
sim.step_until_no_events();
assert_eq!(sim.time(), 10.);
Sourcepub fn recv_event<T>(&self) -> EventFuture<T> ⓘwhere
T: EventData,
Available on crate feature async_mode
only.
pub fn recv_event<T>(&self) -> EventFuture<T> ⓘwhere
T: EventData,
async_mode
only.Waits (asynchronously) for event of type T
from any component.
The returned future outputs the received event and event data.
The timeout for waiting can be set by calling EventFuture::with_timeout
on the returned future.
§Examples
use serde::Serialize;
use simcore::Simulation;
#[derive(Clone, Serialize)]
struct Message {
payload: u32,
}
let mut sim = Simulation::new(123);
let sender_ctx = sim.create_context("sender");
let sender_id = sender_ctx.id();
let receiver_ctx = sim.create_context("receiver");
let receiver_id = receiver_ctx.id();
sim.spawn(async move {
sender_ctx.emit(Message { payload: 321 }, receiver_id, 50.);
});
sim.spawn(async move {
let e = receiver_ctx.recv_event::<Message>().await;
assert_eq!(e.src, sender_id);
assert_eq!(e.data.payload, 321);
});
sim.step_until_no_events();
assert_eq!(sim.time(), 50.);
use serde::Serialize;
use simcore::Simulation;
#[derive(Clone, Serialize)]
struct Message {
payload: u32,
}
let mut sim = Simulation::new(123);
let sender1_ctx = sim.create_context("sender1");
let sender1_id = sender1_ctx.id();
let sender2_ctx = sim.create_context("sender2");
let sender2_id = sender2_ctx.id();
let receiver_ctx = sim.create_context("receiver");
let receiver_id = receiver_ctx.id();
sim.spawn(async move {
sender1_ctx.emit(Message { payload: 321 }, receiver_id, 50.);
});
sim.spawn(async move {
sender2_ctx.emit(Message { payload: 322 }, receiver_id, 100.);
});
sim.spawn(async move {
let e = receiver_ctx.recv_event::<Message>().await;
assert_eq!(receiver_ctx.time(), 50.);
assert_eq!(e.src, sender1_id);
assert_eq!(e.data.payload, 321);
let e = receiver_ctx.recv_event::<Message>().await;
assert_eq!(receiver_ctx.time(), 100.);
assert_eq!(e.src, sender2_id);
assert_eq!(e.data.payload, 322);
});
sim.step_until_no_events();
assert_eq!(sim.time(), 100.);
Sourcepub fn recv_event_from<T>(&self, src: Id) -> EventFuture<T> ⓘwhere
T: EventData,
Available on crate feature async_mode
only.
pub fn recv_event_from<T>(&self, src: Id) -> EventFuture<T> ⓘwhere
T: EventData,
async_mode
only.Waits (asynchronously) for event of type T
from component src
.
The returned future outputs the received event and event data.
The timeout for waiting can be set by calling EventFuture::with_timeout
on the returned future.
§Examples
use serde::Serialize;
use simcore::Simulation;
#[derive(Clone, Serialize)]
struct Message {
payload: u32,
}
let mut sim = Simulation::new(123);
let sender_ctx = sim.create_context("sender");
let sender_id = sender_ctx.id();
let receiver_ctx = sim.create_context("receiver");
let receiver_id = receiver_ctx.id();
sim.spawn(async move {
sender_ctx.emit(Message { payload: 321 }, receiver_id, 50.);
});
sim.spawn(async move {
let e = receiver_ctx.recv_event_from::<Message>(sender_id).await;
assert_eq!(e.src, sender_id);
assert_eq!(e.data.payload, 321);
});
sim.step_until_no_events();
assert_eq!(sim.time(), 50.);
Sourcepub fn recv_event_from_self<T>(&self) -> EventFuture<T> ⓘwhere
T: EventData,
Available on crate feature async_mode
only.
pub fn recv_event_from_self<T>(&self) -> EventFuture<T> ⓘwhere
T: EventData,
async_mode
only.Waits (asynchronously) for event of type T
from self.
The returned future outputs the received event and event data.
The timeout for waiting can be set by calling EventFuture::with_timeout
on the returned future.
§Examples
use serde::Serialize;
use simcore::Simulation;
#[derive(Clone, Serialize)]
struct SomeEvent {
payload: u32,
}
let mut sim = Simulation::new(123);
let ctx = sim.create_context("comp");
sim.spawn(async move {
ctx.emit_self(SomeEvent { payload: 321 }, 10.);
let e = ctx.recv_event_from_self::<SomeEvent>().await;
assert_eq!(e.data.payload, 321);
assert_eq!(ctx.time(), 10.)
});
sim.step_until_no_events();
assert_eq!(sim.time(), 10.);
Sourcepub fn register_key_getter_for<T: EventData>(
&self,
key_getter: impl Fn(&T) -> EventKey + 'static,
)
Available on crate feature async_mode
only.
pub fn register_key_getter_for<T: EventData>( &self, key_getter: impl Fn(&T) -> EventKey + 'static, )
async_mode
only.Registers a key getter function for event type T
to be used with
recv_event_by_key
and recv_event_by_key_from
.
Sourcepub fn recv_event_by_key<T>(&self, key: EventKey) -> EventFuture<T> ⓘwhere
T: EventData,
Available on crate feature async_mode
only.
pub fn recv_event_by_key<T>(&self, key: EventKey) -> EventFuture<T> ⓘwhere
T: EventData,
async_mode
only.Waits (asynchronously) for event of type T
with key key
from any component.
The returned future outputs the received event and event data.
The timeout for waiting can be set by calling EventFuture::with_timeout
on the returned future.
See recv_event_by_key_from
and recv_event
for examples.
Sourcepub fn recv_event_by_key_from<T>(
&self,
src: Id,
key: EventKey,
) -> EventFuture<T> ⓘwhere
T: EventData,
Available on crate feature async_mode
only.
pub fn recv_event_by_key_from<T>(
&self,
src: Id,
key: EventKey,
) -> EventFuture<T> ⓘwhere
T: EventData,
async_mode
only.Waits (asynchronously) for event of type T
with key key
from component src
.
The returned future outputs the received event and event data.
The timeout for waiting can be set by calling EventFuture::with_timeout
on the returned future.
§Examples
use std::{cell::RefCell, rc::Rc};
use serde::Serialize;
use simcore::{cast, Id, Event, StaticEventHandler, Simulation, SimulationContext};
use simcore::async_mode::EventKey;
#[derive(Clone, Serialize)]
struct SomeEvent {
key: u64,
payload: u32,
}
#[derive(Clone, Serialize)]
struct Start {
}
struct Component {
ctx: SimulationContext,
root_id: Id,
}
impl Component {
async fn recv_event_for_key(self: Rc<Self>, key: EventKey) {
let e = self.ctx.recv_event_by_key_from::<SomeEvent>(self.root_id, key).await;
assert_eq!(e.data.key, key);
}
}
impl StaticEventHandler for Component {
fn on(self: Rc<Self>, event: Event) {
cast!(match event.data {
Start {} => {
self.ctx.spawn(self.clone().recv_event_for_key(1));
self.ctx.spawn(self.clone().recv_event_for_key(2));
}
})
}
}
let mut sim = Simulation::new(124);
let root_ctx = sim.create_context("sender");
let comp_ctx = sim.create_context("comp");
let comp_id = sim.add_static_handler("comp", Rc::new(Component { ctx: comp_ctx, root_id: root_ctx.id() }));
sim.register_key_getter_for::<SomeEvent>(|message| message.key);
root_ctx.emit_now(Start {}, comp_id);
root_ctx.emit(SomeEvent { key: 1, payload: 321 }, comp_id, 50.);
root_ctx.emit(SomeEvent { key: 2, payload: 322 }, comp_id, 100.);
sim.step_until_no_events();
assert_eq!(sim.time(), 100.);
Sourcepub fn recv_event_by_key_from_self<T>(&self, key: EventKey) -> EventFuture<T> ⓘwhere
T: EventData,
Available on crate feature async_mode
only.
pub fn recv_event_by_key_from_self<T>(&self, key: EventKey) -> EventFuture<T> ⓘwhere
T: EventData,
async_mode
only.Waits (asynchronously) for event of type T
with key key
from self.
The returned future outputs the received event and event data.
The timeout for waiting can be set by calling EventFuture::with_timeout
on the returned future.
See recv_event_by_key_from
and recv_event_from_self
for examples.
Auto Trait Implementations§
impl Freeze for SimulationContext
impl !RefUnwindSafe for SimulationContext
impl !Send for SimulationContext
impl !Sync for SimulationContext
impl Unpin for SimulationContext
impl !UnwindSafe for SimulationContext
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.