d3_core/collective/
machine.rs

1#[allow(unused_imports)] use super::*;
2
3// The MachineBuilder lives in d3-collective. This is due to a
4// dependency upon ShareableMachine and Sender.
5
6// The MachineBuilder forms the interface between the machine and
7// the collective. Each instruction set provides a means of
8// tranforming a stand-alone machine into a collective, where it
9// can interact with other machines.
10//
11// Building consists of wrapping a raw machine, so that it can be
12// shared with the collective. A communications channel is added,
13// which is provided for sending instructions into the machine,
14// the receiver is owned by the collective.
15//
16// Although it may not be usual, a machine may support multiple
17// instruction sets.
18//
19#[doc(hidden)]
20pub trait MachineBuilder {
21    // The instruction set implemented by the machine
22    type InstructionSet: MachineImpl;
23
24    // build with a fixed size queue capacity
25    fn build_raw<T>(raw: T, channel_capacity: usize) -> (Arc<Mutex<T>>, Sender<Self::InstructionSet>, MachineAdapter)
26    where
27        T: 'static + Machine<Self::InstructionSet>,
28        <Self as MachineBuilder>::InstructionSet: Send;
29
30    // add an instruction set
31    fn build_addition<T>(machine: &Arc<Mutex<T>>, channel_capacity: usize) -> (Sender<Self::InstructionSet>, MachineAdapter)
32    where
33        T: 'static + Machine<Self::InstructionSet>;
34
35    // build with an unbounded queue capacity
36    fn build_unbounded<T>(raw: T) -> (Arc<Mutex<T>>, Sender<Self::InstructionSet>, MachineAdapter)
37    where
38        T: 'static + Machine<Self::InstructionSet>,
39        <Self as MachineBuilder>::InstructionSet: Send;
40
41    // add an instruction set
42    fn build_addition_unbounded<T>(machine: &Arc<Mutex<T>>) -> (Sender<Self::InstructionSet>, MachineAdapter)
43    where
44        T: 'static + Machine<Self::InstructionSet>,
45        <Self as MachineBuilder>::InstructionSet: Send;
46    // common building, both build() and build_unbounded() should call into build_common()
47    fn build_common<T>(
48        raw: T, s: Sender<Self::InstructionSet>, r: Receiver<Self::InstructionSet>,
49    ) -> (Arc<Mutex<T>>, Sender<Self::InstructionSet>, MachineAdapter)
50    where
51        T: 'static + Machine<Self::InstructionSet>,
52        <Self as MachineBuilder>::InstructionSet: Send;
53
54    fn build_addition_common<T>(
55        machine: &Arc<Mutex<T>>, sender: Sender<Self::InstructionSet>, receiver: Receiver<Self::InstructionSet>,
56    ) -> (Sender<Self::InstructionSet>, MachineAdapter)
57    where
58        T: 'static + Machine<Self::InstructionSet>;
59}
60
61/// Send an instruction to a sender and log any errors. The instruction set
62/// must implement Debug in order to use it in send_cmd()
63///
64/// # examples
65///
66/// ```
67/// # use d3_core::machine_impl::*;
68/// # use d3_derive::*;
69/// # use std::sync::Arc;
70/// # use parking_lot::Mutex;
71/// # use d3_core::send_cmd;
72/// # #[derive(Debug,MachineImpl)] pub enum StateTable { Start, Stop }
73/// #
74/// let (sender, receiver) = channel::<StateTable>();
75/// send_cmd(&sender, StateTable::Start);
76/// ```
77#[inline]
78pub fn send_cmd<T>(sender: &Sender<T>, cmd: T)
79where
80    T: MachineImpl + MachineImpl<InstructionSet = T> + std::fmt::Debug,
81{
82    match sender.send(cmd) {
83        Ok(_) => (),
84        Err(e) => log::info!("failed to send instruction: {}", e),
85    }
86}