Skip to content

Commit

Permalink
Use match expressions in the internal and external transition functio…
Browse files Browse the repository at this point in the history
…ns, for easier interpretation of state space and state variable conditionals
  • Loading branch information
ndebuhr committed Jul 14, 2021
1 parent 5bb9246 commit d5447d2
Show file tree
Hide file tree
Showing 10 changed files with 304 additions and 245 deletions.
27 changes: 11 additions & 16 deletions sim/src/models/batcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,29 +139,24 @@ impl AsModel for Batcher {
incoming_message: &ModelMessage,
_services: &mut Services,
) -> Result<(), SimulationError> {
if self.state.phase == Phase::Batching && self.state.jobs.len() + 1 < self.max_batch_size {
self.add_to_batch(incoming_message)
} else if self.state.phase == Phase::Passive
&& self.state.jobs.len() + 1 < self.max_batch_size
{
self.start_batch(incoming_message)
} else if self.state.jobs.len() + 1 >= self.max_batch_size {
self.fill_batch(incoming_message)
} else {
Err(SimulationError::InvalidModelState)
match (
&self.state.phase,
self.state.jobs.len() + 1 < self.max_batch_size,
) {
(Phase::Batching, true) => self.add_to_batch(incoming_message),
(Phase::Passive, true) => self.start_batch(incoming_message),
(Phase::Release, true) => Err(SimulationError::InvalidModelState),
(_, false) => self.fill_batch(incoming_message),
}
}

fn events_int(
&mut self,
_services: &mut Services,
) -> Result<Vec<ModelMessage>, SimulationError> {
if self.state.jobs.len() <= self.max_batch_size {
self.release_full_queue()
} else if self.state.jobs.len() <= self.max_batch_size {
self.release_partial_queue()
} else {
Err(SimulationError::InvalidModelState)
match self.state.jobs.len() <= self.max_batch_size {
true => self.release_full_queue(),
false => self.release_partial_queue(),
}
}

Expand Down
58 changes: 29 additions & 29 deletions sim/src/models/exclusive_gateway.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ struct State {
impl Default for State {
fn default() -> Self {
State {
phase: Phase::Idle,
phase: Phase::Passive,
until_next_event: INFINITY,
jobs: Vec::new(),
records: Vec::new(),
Expand All @@ -66,7 +66,7 @@ impl Default for State {

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
enum Phase {
Idle, // Doing nothing
Passive, // Doing nothing
Pass, // Passing a job from input to output
Respond, // Responding to a records request
}
Expand Down Expand Up @@ -148,8 +148,12 @@ impl ExclusiveGateway {
Ok(())
}

fn ignore_request(&mut self) -> Result<(), SimulationError> {
Ok(())
}

fn send_records(&mut self) -> Result<Vec<ModelMessage>, SimulationError> {
self.state.phase = Phase::Idle;
self.state.phase = Phase::Passive;
self.state.until_next_event = INFINITY;
Ok(vec![ModelMessage {
port_name: self.ports_out.records.clone(),
Expand All @@ -158,7 +162,7 @@ impl ExclusiveGateway {
}

fn send_jobs(&mut self) -> Result<Vec<ModelMessage>, SimulationError> {
self.state.phase = Phase::Idle;
self.state.phase = Phase::Passive;
self.state.until_next_event = INFINITY;
Ok((0..self.state.jobs.len())
.map(|_| {
Expand All @@ -170,12 +174,18 @@ impl ExclusiveGateway {
})
.collect())
}

fn passivate(&mut self) -> Result<Vec<ModelMessage>, SimulationError> {
self.state.phase = Phase::Passive;
self.state.until_next_event = INFINITY;
Ok(Vec::new())
}
}

impl AsModel for ExclusiveGateway {
fn status(&self) -> String {
match self.state.phase {
Phase::Idle => String::from("Idle"),
Phase::Passive => String::from("Passive"),
Phase::Pass => format!["Passing {}", self.state.jobs[0].content],
Phase::Respond => String::from("Fetching records"),
}
Expand All @@ -186,37 +196,27 @@ impl AsModel for ExclusiveGateway {
incoming_message: &ModelMessage,
services: &mut Services,
) -> Result<(), SimulationError> {
if self
.ports_in
.flow_paths
.contains(&incoming_message.port_name)
&& !self.store_records
{
self.pass_job(incoming_message, services)
} else if self
.ports_in
.flow_paths
.contains(&incoming_message.port_name)
&& self.store_records
{
self.store_job(incoming_message, services)
} else if self.ports_in.records == incoming_message.port_name {
self.records_request()
} else {
Err(SimulationError::InvalidModelState)
match (
self.ports_in
.flow_paths
.contains(&incoming_message.port_name),
self.store_records,
) {
(true, true) => self.store_job(incoming_message, services),
(true, false) => self.pass_job(incoming_message, services),
(false, true) => self.records_request(),
(false, false) => self.ignore_request(),
}
}

fn events_int(
&mut self,
_services: &mut Services,
) -> Result<Vec<ModelMessage>, SimulationError> {
if Phase::Pass == self.state.phase {
self.send_jobs()
} else if Phase::Respond == self.state.phase {
self.send_records()
} else {
Err(SimulationError::InvalidModelState)
match &self.state.phase {
Phase::Passive => self.passivate(),
Phase::Pass => self.send_jobs(),
Phase::Respond => self.send_records(),
}
}

Expand Down
78 changes: 42 additions & 36 deletions sim/src/models/gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ struct PortsIn {
records: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
enum ArrivalPort {
Job,
Activation,
Deactivation,
Records,
Unknown,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
struct PortsOut {
job: String,
Expand Down Expand Up @@ -105,6 +114,20 @@ impl Gate {
}
}

fn arrival_port(&self, message_port: &str) -> ArrivalPort {
if message_port == self.ports_in.job {
ArrivalPort::Job
} else if message_port == self.ports_in.activation {
ArrivalPort::Activation
} else if message_port == self.ports_in.deactivation {
ArrivalPort::Deactivation
} else if message_port == self.ports_in.records {
ArrivalPort::Records
} else {
ArrivalPort::Unknown
}
}

fn activate(&mut self) -> Result<(), SimulationError> {
self.state.phase = Phase::Open;
self.state.until_next_event = INFINITY;
Expand Down Expand Up @@ -225,49 +248,32 @@ impl AsModel for Gate {
incoming_message: &ModelMessage,
services: &mut Services,
) -> Result<(), SimulationError> {
if self.ports_in.activation == incoming_message.port_name {
self.activate()
} else if self.ports_in.deactivation == incoming_message.port_name {
self.deactivate()
} else if self.ports_in.job == incoming_message.port_name
&& !(self.state.phase == Phase::Closed)
&& !self.store_records
{
self.pass_job(incoming_message, services)
} else if self.ports_in.job == incoming_message.port_name
&& !(self.state.phase == Phase::Closed)
&& self.store_records
{
self.store_job(incoming_message, services)
} else if self.ports_in.job == incoming_message.port_name
&& self.state.phase == Phase::Closed
{
self.drop_job(incoming_message, services)
} else if self.ports_in.records == incoming_message.port_name
&& !(self.state.phase == Phase::Closed)
{
self.records_request_while_open()
} else if self.ports_in.records == incoming_message.port_name
&& Phase::Closed == self.state.phase
{
self.records_request_while_closed()
} else {
Err(SimulationError::InvalidModelState)
match (
self.arrival_port(&incoming_message.port_name),
self.state.phase == Phase::Closed,
self.store_records,
) {
(ArrivalPort::Activation, _, _) => self.activate(),
(ArrivalPort::Deactivation, _, _) => self.deactivate(),
(ArrivalPort::Job, false, false) => self.pass_job(incoming_message, services),
(ArrivalPort::Job, false, true) => self.store_job(incoming_message, services),
(ArrivalPort::Job, true, _) => self.drop_job(incoming_message, services),
(ArrivalPort::Records, false, _) => self.records_request_while_open(),
(ArrivalPort::Records, true, _) => self.records_request_while_closed(),
(ArrivalPort::Unknown, _, _) => Err(SimulationError::InvalidMessage),
}
}

fn events_int(
&mut self,
_services: &mut Services,
) -> Result<Vec<ModelMessage>, SimulationError> {
if ![Phase::RespondWhileOpen, Phase::RespondWhileClosed].contains(&self.state.phase) {
self.send_jobs()
} else if self.state.phase == Phase::RespondWhileOpen {
self.send_records_while_open()
} else if self.state.phase == Phase::RespondWhileClosed {
self.send_records_while_closed()
} else {
Err(SimulationError::InvalidModelState)
match &self.state.phase {
Phase::Open => self.send_jobs(),
Phase::Closed => self.send_jobs(),
Phase::Pass => self.send_jobs(),
Phase::RespondWhileOpen => self.send_records_while_open(),
Phase::RespondWhileClosed => self.send_records_while_closed(),
}
}

Expand Down
28 changes: 10 additions & 18 deletions sim/src/models/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,31 +195,23 @@ impl AsModel for Generator {
incoming_message: &ModelMessage,
services: &mut Services,
) -> Result<(), SimulationError> {
if self.store_records {
self.request_records(incoming_message, services)
} else if !self.store_records {
self.ignore_request(incoming_message, services)
} else {
Err(SimulationError::InvalidModelState)
match &self.store_records {
true => self.request_records(incoming_message, services),
false => self.ignore_request(incoming_message, services),
}
}

fn events_int(
&mut self,
services: &mut Services,
) -> Result<Vec<ModelMessage>, SimulationError> {
if self.state.phase == Phase::Generating && self.store_records {
self.save_job(services)
} else if (self.state.phase == Phase::Generating && !self.store_records)
|| self.state.phase == Phase::Saved
{
self.release_job(services)
} else if self.state.phase == Phase::RecordsFetch {
self.release_records()
} else if self.state.phase == Phase::Initializing {
self.initialize_generation(services)
} else {
Err(SimulationError::InvalidModelState)
match (&self.state.phase, self.store_records) {
(Phase::Generating, true) => self.save_job(services),
(Phase::Generating, false) => self.release_job(services),
(Phase::Saved, _) => self.release_job(services),
(Phase::RecordsFetch, true) => self.release_records(),
(Phase::RecordsFetch, false) => Err(SimulationError::InvalidModelState),
(Phase::Initializing, _) => self.initialize_generation(services),
}
}

Expand Down
48 changes: 30 additions & 18 deletions sim/src/models/load_balancer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ struct PortsIn {
records: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
enum ArrivalPort {
Job,
Records,
Unknown,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct PortsOut {
Expand Down Expand Up @@ -90,6 +97,16 @@ impl LoadBalancer {
}
}

fn arrival_port(&self, message_port: &str) -> ArrivalPort {
if message_port == self.ports_in.job {
ArrivalPort::Job
} else if message_port == self.ports_in.records {
ArrivalPort::Records
} else {
ArrivalPort::Unknown
}
}

fn request_records(
&mut self,
_incoming_message: &ModelMessage,
Expand Down Expand Up @@ -180,31 +197,26 @@ impl AsModel for LoadBalancer {
incoming_message: &ModelMessage,
services: &mut Services,
) -> Result<(), SimulationError> {
if incoming_message.port_name == self.ports_in.records && self.store_records {
self.request_records(incoming_message, services)
} else if incoming_message.port_name == self.ports_in.records && !self.store_records {
self.ignore_request(incoming_message, services)
} else if incoming_message.port_name == self.ports_in.job && self.store_records {
self.save_job(incoming_message, services)
} else if incoming_message.port_name == self.ports_in.job && !self.store_records {
self.pass_job(incoming_message, services)
} else {
Err(SimulationError::InvalidModelState)
match (
self.arrival_port(&incoming_message.port_name),
self.store_records,
) {
(ArrivalPort::Records, true) => self.request_records(incoming_message, services),
(ArrivalPort::Records, false) => self.ignore_request(incoming_message, services),
(ArrivalPort::Job, true) => self.save_job(incoming_message, services),
(ArrivalPort::Job, false) => self.pass_job(incoming_message, services),
(ArrivalPort::Unknown, _) => Err(SimulationError::InvalidMessage),
}
}

fn events_int(
&mut self,
_services: &mut Services,
) -> Result<Vec<ModelMessage>, SimulationError> {
if self.state.phase == Phase::RecordsFetch {
self.release_records()
} else if self.state.phase == Phase::LoadBalancing && self.state.jobs.is_empty() {
self.passivate()
} else if self.state.phase == Phase::LoadBalancing && !self.state.jobs.is_empty() {
self.send_job()
} else {
Err(SimulationError::InvalidModelState)
match (&self.state.phase, self.state.jobs.is_empty()) {
(Phase::RecordsFetch, _) => self.release_records(),
(Phase::LoadBalancing, true) => self.passivate(),
(Phase::LoadBalancing, false) => self.send_job(),
}
}

Expand Down
Loading

0 comments on commit d5447d2

Please sign in to comment.