Skip to content

Commit

Permalink
feat: extended counter updates and add signalling.
Browse files Browse the repository at this point in the history
- Added support for internal signaling between machines with
  Event::Signal.
- It is now possible to update both counters on state transition.
- A counter operation can now use the value of the other counter.
- Updated changelog, also with minor clarifications.
  • Loading branch information
ewitwer authored and pylls committed Sep 4, 2024
1 parent 551e5b0 commit 5fe5e33
Show file tree
Hide file tree
Showing 10 changed files with 835 additions and 252 deletions.
2 changes: 1 addition & 1 deletion crates/maybenot-simulator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
//!
//! // A simple machine that sends one padding packet 20 milliseconds after the
//! // first normal packet is sent.
//! let m = "02eNptibEJAAAIw1of09Mc/c+HRMFFzFBoAlxkliTgurLfT6T9oQBWJgJi";
//! let m = "02eNp1ibEJAEAIA5Nf7B3N0v1cSESwEL0m5A6YvBqSgP7WeXfM5UoBW7ICYg==";
//! let m = Machine::from_str(m).unwrap();
//!
//! // Run the simulator with the machine at the client. Run the simulation up
Expand Down
4 changes: 2 additions & 2 deletions crates/maybenot-simulator/tests/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn simple_machine_for_example() {
let m = Machine::new(0, 0.0, 0, 0.0, vec![s0, s1]).unwrap();
assert_eq!(
m.serialize(),
"02eNptibEJAAAIw1of09Mc/c+HRMFFzFBoAlxkliTgurLfT6T9oQBWJgJi"
"02eNp1ibEJAEAIA5Nf7B3N0v1cSESwEL0m5A6YvBqSgP7WeXfM5UoBW7ICYg=="
);
}

Expand Down Expand Up @@ -67,7 +67,7 @@ fn simulator_example_use() {

// A simple machine that sends one padding packet 20 milliseconds after the
// first normal packet is sent.
let m = "02eNptibEJAAAIw1of09Mc/c+HRMFFzFBoAlxkliTgurLfT6T9oQBWJgJi";
let m = "02eNp1ibEJAEAIA5Nf7B3N0v1cSESwEL0m5A6YvBqSgP7WeXfM5UoBW7ICYg==";
let m = Machine::from_str(m).unwrap();

// Run the simulator with the machine at the client. Run the simulation up
Expand Down
138 changes: 70 additions & 68 deletions crates/maybenot-simulator/tests/simulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::time::Duration;

use maybenot::{
action::Action,
counter::{Counter, CounterUpdate, Operation},
counter::{Counter, Operation},
dist::{Dist, DistType},
event::Event,
state::{State, Trans},
Expand Down Expand Up @@ -1086,44 +1086,44 @@ fn test_counter_machine() {
Event::NormalRecv => vec![Trans(2, 1.0)],
_ => vec![],
});
s1.counter = Some(CounterUpdate {
counter: Counter::A,
operation: Operation::Increment,
value: Some(Dist {
dist: DistType::Uniform {
low: 5.0,
high: 5.0,
s1.counter = (
Some(Counter::new_dist(
Operation::Increment,
Dist {
dist: DistType::Uniform {
low: 5.0,
high: 5.0,
},
start: 0.0,
max: 0.0,
},
start: 0.0,
max: 0.0,
}),
});
)),
None,
);
let mut s2 = State::new(enum_map! {
Event::NormalRecv => vec![Trans(3, 1.0)],
_ => vec![],
});
s2.counter = Some(CounterUpdate {
counter: Counter::A,
operation: Operation::Decrement,
value: Some(Dist {
dist: DistType::Uniform {
low: 2.0,
high: 2.0,
s2.counter = (
Some(Counter::new_dist(
Operation::Decrement,
Dist {
dist: DistType::Uniform {
low: 2.0,
high: 2.0,
},
start: 0.0,
max: 0.0,
},
start: 0.0,
max: 0.0,
}),
});
)),
None,
);
let mut s3 = State::new(enum_map! {
Event::NormalSent => vec![Trans(3, 1.0)],
Event::CounterZero => vec![Trans(4, 1.0)],
_ => vec![],
});
s3.counter = Some(CounterUpdate {
counter: Counter::A,
operation: Operation::Decrement,
value: None, // same as 1
});
s3.counter = (Some(Counter::new(Operation::Decrement)), None);
let mut s4 = State::new(enum_map! {
_ => vec![],
});
Expand Down Expand Up @@ -1153,13 +1153,9 @@ fn test_counter_machine() {
false,
);

// set counter in state 3 to Counter::B, to prevent the CounterZero event
// set counter in state 3 to Counter B, to prevent the CounterZero event
// from firing
m.states[3].counter = Some(CounterUpdate {
counter: Counter::B,
operation: Operation::Decrement,
value: None,
});
m.states[3].counter = (None, Some(Counter::new(Operation::Decrement)));
run_test_sim(
"0,sn 6,rn 6,rn 7,sn 7,sn 7,sn",
"0,sn 0,st 6,rt 6,rt 6,rn 6,rn 7,sn 7,st 7,sn 7,st 7,sn 7,st",
Expand All @@ -1171,31 +1167,35 @@ fn test_counter_machine() {
false,
);

// update state 1 and 2 to also use Counter::B
m.states[1].counter = Some(CounterUpdate {
counter: Counter::B,
operation: Operation::Increment,
value: Some(Dist {
dist: DistType::Uniform {
low: 5.0,
high: 5.0,
// update state 1 and 2 to also use Counter B
m.states[1].counter = (
None,
Some(Counter::new_dist(
Operation::Increment,
Dist {
dist: DistType::Uniform {
low: 5.0,
high: 5.0,
},
start: 0.0,
max: 0.0,
},
start: 0.0,
max: 0.0,
}),
});
m.states[2].counter = Some(CounterUpdate {
counter: Counter::B,
operation: Operation::Decrement,
value: Some(Dist {
dist: DistType::Uniform {
low: 2.0,
high: 2.0,
)),
);
m.states[2].counter = (
None,
Some(Counter::new_dist(
Operation::Decrement,
Dist {
dist: DistType::Uniform {
low: 2.0,
high: 2.0,
},
start: 0.0,
max: 0.0,
},
start: 0.0,
max: 0.0,
}),
});
)),
);
run_test_sim(
"0,sn 6,rn 6,rn 7,sn 7,sn 7,sn",
"0,sn 0,st 6,rt 6,rt 6,rn 6,rn 7,sn 7,st 7,sn 7,st 7,sn 7,st 10,sp 10,st",
Expand All @@ -1208,18 +1208,20 @@ fn test_counter_machine() {
);

// replace increment in state 1 with set operation, should make no difference
m.states[1].counter = Some(CounterUpdate {
counter: Counter::B,
operation: Operation::Set,
value: Some(Dist {
dist: DistType::Uniform {
low: 5.0,
high: 5.0,
m.states[1].counter = (
None,
Some(Counter::new_dist(
Operation::Set,
Dist {
dist: DistType::Uniform {
low: 5.0,
high: 5.0,
},
start: 0.0,
max: 0.0,
},
start: 0.0,
max: 0.0,
}),
});
)),
);
run_test_sim(
"0,sn 6,rn 6,rn 7,sn 7,sn 7,sn",
"0,sn 0,st 6,rt 6,rt 6,rn 6,rn 7,sn 7,st 7,sn 7,st 7,sn 7,st 10,sp 10,st",
Expand Down
11 changes: 8 additions & 3 deletions crates/maybenot/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,18 @@ Manually generated changelog, for now. We follow semantic versioning.
machines and effectively dealing with blocking actions.
- Added two counters per machine which are updated upon transition to a state if
its `counter` field is set. A `CounterZero` event is triggered when either of
a machine's counters is decremented to zero.
a machine's counters is decremented to zero. Counters are internal to the
framework and are not exposed to the integrator.
- Added a per-machine "internal" timer which can be set using an `UpdateTimer`
action. These are handled by the integrator, who triggers the corresponding
`TimerBegin` and `TimerEnd` events as the timer starts and fire.
action. These are handled by the integrator (to not impose any particular
runtime for timers), who triggers the corresponding `TimerBegin` and
`TimerEnd` events as the timer starts and fire.
- Extended the `Cancel` action that can be used to cancel a pending action timer
(timeout), the machine's internal timer, or both. The internal pseudo-state
`STATE_CANCEL` transition is removed.
- Added support for `Event::Signal`, allowing machines to signal between each
other. Useful for multiple machines that need to coordinate their states. This
is internal to the framework and is not exposed to the integrator.
- Added support for the `SkewNormal` distribution.
- Added an optional `parsing` feature to reconstruct v1 machines, though they
may behave differently than expected. v1 machines are now deprecated.
Expand Down
7 changes: 5 additions & 2 deletions crates/maybenot/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub const VERSION: u8 = 2;
pub const MAX_DECOMPRESSED_SIZE: usize = 1 << 20;

/// The number of [`Event`](crate::event)s in the framework.
pub const EVENT_NUM: usize = 12;
pub const EVENT_NUM: usize = 13;

/// The maximum sampled timeout in a [`State`](crate::state), set to a day in
/// microseconds.
Expand Down Expand Up @@ -38,6 +38,9 @@ pub const STATE_NOP: usize = u32::MAX as usize;
/// A pseudo-state that means the [`Machine`](crate::Machine) should completely
/// stop.
pub const STATE_END: usize = STATE_NOP - 1;
/// A pseudo-state that triggers a Signal [`Event`](crate::event) in all other
/// running machines.
pub const STATE_SIGNAL: usize = STATE_END - 1;
/// The maximum number of [`State`](crate::state)s a [`Machine`](crate::Machine)
/// can have.
pub const STATE_MAX: usize = STATE_END - 1;
pub const STATE_MAX: usize = STATE_SIGNAL - 1;
Loading

0 comments on commit 5fe5e33

Please sign in to comment.