Skip to main content

proto_lab/
network_simulator.rs

1use std::{
2    cell::RefCell,
3    ops::DerefMut,
4    sync::{Arc, Mutex},
5};
6
7use crate::EtherSimulator;
8
9pub struct NetworkSimulator {
10    ethers: RefCell<Option<Vec<EtherSimulator>>>,
11    ms_per_tick: u64,
12    simulation_thread_handle: Option<std::thread::JoinHandle<Vec<EtherSimulator>>>,
13    thread_killer: Arc<Mutex<bool>>,
14}
15
16/// NetworkSimulator is designed to simulate the network which consist of 1+ ethers.
17/// Each ether is instance of EtherSimulator
18impl NetworkSimulator {
19    pub fn new(ms_per_tick: u64) -> Self {
20        NetworkSimulator {
21            ethers: RefCell::new(Some(Vec::new())),
22            ms_per_tick,
23            simulation_thread_handle: None,
24            thread_killer: Arc::new(Mutex::new(false)),
25        }
26    }
27
28    pub fn create_ether(&self, name: &str) {
29        match self.ethers.borrow_mut().deref_mut() {
30            Some(ref mut ethers) => {
31                let new_ether = EtherSimulator::new(name);
32                ethers.push(new_ether);
33            }
34            None => {
35                panic!("Simulation thread is already started. Can not change configuration")
36            }
37        };
38    }
39
40    pub fn get_ether(&self, name: &str) -> Option<EtherSimulator> {
41        match self.ethers.borrow_mut().deref_mut() {
42            None => panic!("Simulation thread is started. Can not get ether"),
43            Some(ref ethers) => {
44                for ether in ethers.iter() {
45                    if ether.get_name() == name {
46                        return Some(ether.clone());
47                    }
48                }
49                None
50            }
51        }
52    }
53
54    pub fn start_tick(&self) {
55        match self.ethers.borrow_mut().deref_mut() {
56            None => panic!(
57                "Simulation thread is started. Can not do start_tick and thread at the same time"
58            ),
59            Some(ref ethers) => {
60                for ether in ethers.iter() {
61                    ether.start_tick();
62                }
63            }
64        }
65    }
66
67    pub fn end_tick(&self) {
68        match self.ethers.borrow_mut().deref_mut() {
69            None => panic!(
70                "Simulation thread is started. Can not do start_tick and thread at the same time"
71            ),
72            Some(ref ethers) => {
73                for ether in ethers.iter() {
74                    ether.end_tick();
75                }
76            }
77        }
78    }
79
80    pub fn simulate(&self) {
81        match self.ethers.borrow_mut().deref_mut() {
82            None => panic!(
83                "Simulation thread is started. Can not do start_tick and thread at the same time"
84            ),
85            Some(ref mut ethers) => {
86                for ether in ethers.iter_mut() {
87                    ether.simulate();
88                }
89            }
90        }
91    }
92
93    pub fn start_simulation_thread(&mut self) {
94        match self.simulation_thread_handle {
95            Some(_) => panic!("Simulation thread is already started"),
96            None => {
97                let mut ethers = self.ethers.take().unwrap();
98
99                let ms_per_tick = self.ms_per_tick;
100                let thread_killer_clone = Arc::clone(&self.thread_killer);
101
102                *self
103                    .thread_killer
104                    .lock()
105                    .expect("Fail to get lock on thread killer") = false;
106
107                self.simulation_thread_handle = Some(std::thread::spawn(move || {
108                    loop {
109                        if *thread_killer_clone
110                            .lock()
111                            .expect("Faild to get lock on clonned thread killer")
112                        {
113                            break;
114                        }
115                        std::thread::sleep(std::time::Duration::from_millis(ms_per_tick));
116                        for ether in ethers.iter_mut() {
117                            ether.start_tick();
118                        }
119                        for ether in ethers.iter_mut() {
120                            ether.simulate();
121                        }
122                        for ether in ethers.iter_mut() {
123                            ether.end_tick();
124                        }
125                    }
126                    ethers
127                }));
128            }
129        }
130    }
131
132    pub fn stop_simulation_thread(&mut self) {
133        self.simulation_thread_handle = match self.simulation_thread_handle.take() {
134            None => panic!("Simulation thread is not started"),
135            Some(simulation_thread_handle) => {
136                *self
137                    .thread_killer
138                    .lock()
139                    .expect("Fail to get lock on thread killer") = true;
140                self.ethers.replace(Some(
141                    simulation_thread_handle
142                        .join()
143                        .expect(" Fail to join simulation thread to get ethers back"),
144                ));
145                None
146            }
147        };
148    }
149}