d3_components/
network_start_stop.rs

1#![allow(dead_code)]
2use super::*;
3
4use crate::mio_network::new_network_factory;
5
6/// Internally, an AtomicCell<NetworkState>, is used for determining the state
7/// of the network. This used by start_network(), stop_network(). An
8/// AtomicRefCell<Network> is used to access the network struct. Both are operating
9/// as singletons, which I'm really not happy with.
10#[allow(non_upper_case_globals)]
11static network_state: AtomicCell<NetworkState> = AtomicCell::new(NetworkState::Stopped);
12
13#[allow(non_upper_case_globals)]
14static network: AtomicRefCell<Network> = AtomicRefCell::new(Network {
15    network_control: NetworkField::Uninitialized,
16    network_sender: NetworkField::Uninitialized,
17});
18
19/// The NetworkState describes each of the states the network can be in
20#[derive(Debug, Copy, Clone, Eq, PartialEq, SmartDefault)]
21enum NetworkState {
22    #[default]
23    Stopped,
24    Initializing,
25    Stopping,
26    Running,
27}
28
29/// NetworkFields are used to allow a default Network struct, the fields
30/// provide an Uninitialized variant, along with a varient for each field
31/// in the Network struct that can't otherwise be defaulted.
32#[derive(SmartDefault)]
33enum NetworkField {
34    #[default]
35    Uninitialized,
36    Network(NetworkControlObj),
37    NetworkSender(NetSender),
38}
39
40/// The Network struct contains fields used by start_network(), stop_network(),
41/// and get_network_sender().
42#[derive(SmartDefault)]
43struct Network {
44    network_control: NetworkField,
45    network_sender: NetworkField,
46}
47impl Network {
48    /// get the network sender
49    fn get_sender() -> NetSender {
50        match &network.borrow().network_sender {
51            NetworkField::NetworkSender(network_sender) => network_sender.clone(),
52            _ => panic!("network is not running, unable to get sender."),
53        }
54    }
55}
56
57#[inline]
58/// Obtain the network's sender. The returned sender is a clone,
59/// that you are free to use, further clone, or drop. Tip: cache
60/// the result and clone it when you need to send it.
61pub fn get_network_sender() -> NetSender { Network::get_sender() }
62
63/// Start the network. Starting does not perform any network bindings, it
64/// prepares the network to accept bindings.
65pub fn start_network() {
66    network_state.store(NetworkState::Initializing);
67    let network_factory = new_network_factory();
68    let network_sender = network_factory.get_sender();
69    let network_control = network_factory.start();
70    let mut s = network.borrow_mut();
71    s.network_control = NetworkField::Network(network_control);
72    s.network_sender = NetworkField::NetworkSender(network_sender);
73    network_state.store(NetworkState::Running);
74}
75
76/// Stop the network. Stopping will close all network connections and
77/// listeners and no further network activity is allowed.
78pub fn stop_network() {
79    network_state.store(NetworkState::Stopping);
80    if let NetworkField::Network(network_control) = &(network.borrow()).network_control {
81        network_control.stop()
82    }
83
84    let mut s = network.borrow_mut();
85    s.network_control = NetworkField::Uninitialized;
86    s.network_sender = NetworkField::Uninitialized;
87    network_state.store(NetworkState::Stopped);
88    // give machines a chance to react to network shutdown
89    thread::sleep(Duration::from_millis(100));
90}
91
92/// The factory for the network
93pub trait NetworkFactory {
94    /// get a clone of the sender for the network
95    fn get_sender(&self) -> NetSender;
96    /// start the network
97    fn start(&self) -> NetworkControlObj;
98}
99/// The trait object for the network factory
100pub type NetworkFactoryObj = Arc<dyn NetworkFactory>;
101
102// The controller for the network.
103pub trait NetworkControl: Send + Sync {
104    /// stop the network
105    fn stop(&self);
106}
107/// The trait object for the network controller
108pub type NetworkControlObj = Arc<dyn NetworkControl>;