Skip to content

Commit

Permalink
Add derived properties
Browse files Browse the repository at this point in the history
  • Loading branch information
k88hudson-cfa committed Oct 22, 2024
1 parent 84f17fc commit 68be521
Show file tree
Hide file tree
Showing 3 changed files with 334 additions and 29 deletions.
3 changes: 2 additions & 1 deletion examples/basic-infection/people.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use ixa::context::Context;
use ixa::context::{Context, Event};
use ixa::define_data_plugin;
use std::collections::HashMap;

Expand All @@ -18,6 +18,7 @@ pub struct InfectionStatusEvent {
pub updated_status: InfectionStatus,
pub person_id: usize,
}
impl Event for InfectionStatusEvent {}

pub trait ContextPeopleExt {
fn create_person(&mut self);
Expand Down
42 changes: 25 additions & 17 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ type Callback = dyn FnOnce(&mut Context);
/// A handler for an event type `E`
type EventHandler<E> = dyn Fn(&mut Context, E);

pub trait Event {
/// Called every time `context.subscribe_to_event` is called with this event
fn on_subscribe(_context: &mut Context) {}
}

/// A manager for the state of a discrete-event simulation
///
/// Provides core simulation services including
Expand Down Expand Up @@ -71,7 +76,7 @@ impl Context {
/// Handlers will be called upon event emission in order of subscription as
/// queued `Callback`s with the appropriate event.
#[allow(clippy::missing_panics_doc)]
pub fn subscribe_to_event<E: Copy + 'static>(
pub fn subscribe_to_event<E: Event + Copy + 'static>(
&mut self,
handler: impl Fn(&mut Context, E) + 'static,
) {
Expand All @@ -81,14 +86,15 @@ impl Context {
.or_insert_with(|| Box::<Vec<Rc<EventHandler<E>>>>::default());
let handler_vec: &mut Vec<Rc<EventHandler<E>>> = handler_vec.downcast_mut().unwrap();
handler_vec.push(Rc::new(handler));
E::on_subscribe(self);
}

/// Emit and event of type E to be handled by registered receivers
///
/// Receivers will handle events in the order that they have subscribed and
/// are queued as callbacks
#[allow(clippy::missing_panics_doc)]
pub fn emit_event<E: Copy + 'static>(&mut self, event: E) {
pub fn emit_event<E: Event + Copy + 'static>(&mut self, event: E) {
// Destructure to obtain event handlers and plan queue
let Context {
event_handlers,
Expand Down Expand Up @@ -414,26 +420,28 @@ mod tests {
}

#[derive(Copy, Clone)]
struct Event {
struct Event1 {
pub data: usize,
}
impl Event for Event1 {}

#[derive(Copy, Clone)]
struct Event2 {
pub data: usize,
}
impl Event for Event2 {}

#[test]
fn simple_event() {
let mut context = Context::new();
let obs_data = Rc::new(RefCell::new(0));
let obs_data_clone = Rc::clone(&obs_data);

context.subscribe_to_event::<Event>(move |_, event| {
context.subscribe_to_event::<Event1>(move |_, event| {
*obs_data_clone.borrow_mut() = event.data;
});

context.emit_event(Event { data: 1 });
context.emit_event(Event1 { data: 1 });
context.execute();
assert_eq!(*obs_data.borrow(), 1);
}
Expand All @@ -444,12 +452,12 @@ mod tests {
let obs_data = Rc::new(RefCell::new(0));
let obs_data_clone = Rc::clone(&obs_data);

context.subscribe_to_event::<Event>(move |_, event| {
context.subscribe_to_event::<Event1>(move |_, event| {
*obs_data_clone.borrow_mut() += event.data;
});

context.emit_event(Event { data: 1 });
context.emit_event(Event { data: 2 });
context.emit_event(Event1 { data: 1 });
context.emit_event(Event1 { data: 2 });
context.execute();

// Both of these should have been received.
Expand All @@ -464,13 +472,13 @@ mod tests {
let obs_data2 = Rc::new(RefCell::new(0));
let obs_data2_clone = Rc::clone(&obs_data2);

context.subscribe_to_event::<Event>(move |_, event| {
context.subscribe_to_event::<Event1>(move |_, event| {
*obs_data1_clone.borrow_mut() = event.data;
});
context.subscribe_to_event::<Event>(move |_, event| {
context.subscribe_to_event::<Event1>(move |_, event| {
*obs_data2_clone.borrow_mut() = event.data;
});
context.emit_event(Event { data: 1 });
context.emit_event(Event1 { data: 1 });
context.execute();
assert_eq!(*obs_data1.borrow(), 1);
assert_eq!(*obs_data2.borrow(), 1);
Expand All @@ -484,13 +492,13 @@ mod tests {
let obs_data2 = Rc::new(RefCell::new(0));
let obs_data2_clone = Rc::clone(&obs_data2);

context.subscribe_to_event::<Event>(move |_, event| {
context.subscribe_to_event::<Event1>(move |_, event| {
*obs_data1_clone.borrow_mut() = event.data;
});
context.subscribe_to_event::<Event2>(move |_, event| {
*obs_data2_clone.borrow_mut() = event.data;
});
context.emit_event(Event { data: 1 });
context.emit_event(Event1 { data: 1 });
context.emit_event(Event2 { data: 2 });
context.execute();
assert_eq!(*obs_data1.borrow(), 1);
Expand All @@ -503,8 +511,8 @@ mod tests {
let obs_data = Rc::new(RefCell::new(0));
let obs_data_clone = Rc::clone(&obs_data);

context.emit_event(Event { data: 1 });
context.subscribe_to_event::<Event>(move |_, event| {
context.emit_event(Event1 { data: 1 });
context.subscribe_to_event::<Event1>(move |_, event| {
*obs_data_clone.borrow_mut() = event.data;
});

Expand Down Expand Up @@ -545,10 +553,10 @@ mod tests {
let mut context = Context::new();
let obs_data = Rc::new(RefCell::new(0));
let obs_data_clone = Rc::clone(&obs_data);
context.subscribe_to_event::<Event>(move |_, event| {
context.subscribe_to_event::<Event1>(move |_, event| {
*obs_data_clone.borrow_mut() = event.data;
});
context.emit_event(Event { data: 1 });
context.emit_event(Event1 { data: 1 });
context.shutdown();
context.execute();
assert_eq!(*obs_data.borrow(), 0);
Expand Down
Loading

0 comments on commit 68be521

Please sign in to comment.