I have a struct that contains two structs with member functions:
pub struct Split <I, A: Clone, B, C, R: ProcessNode<I, A>, D: ProcessNode<A, B>, E: ProcessNode<A, C>> {
_marker: PhantomData<(I, A, B, C)>,
root_node: R,
node1: D,
node2: E
}
Where ProcessNode is just a trait saying there exists a function fn(A) -> B:
pub trait ProcessNode<A, B> {
fn process(&mut self, input: A) -> B;
}
I also implement ProcessNode for Split, which should take in an input A and outputs (B, C). Currently my implementation looks like this:
impl <I, A: Clone, B, C, R: ProcessNode<I, A>, D: ProcessNode<A, B>, E: ProcessNode<A, C>>ProcessNode<I, (B, C)> for Split<I, A, B, C, R, D, E> {
#[inline]
fn process(&mut self, input: I) -> (B, C) {
let intermediate = self.root_node.process(input);
// Run both nodes on intermediate
(self.node1.process(intermediate.clone()), self.node2.process(intermediate))
}
}
but I want to run both nodes in parallel on separate threads. I tried this:
impl <I, A: Clone + Send, B: Send, C: Send, R: ProcessNode<I, A>, D: ProcessNode<A, B>, E: ProcessNode<A, C>>ProcessNode<I, (B, C)> for Split<I, A, B, C, R, D, E> {
#[inline]
fn process(&mut self, input: I) -> (B, C) {
let intermediate1 = self.root_node.process(input);
let intermediate2 = intermediate1.clone();
// Run both nodes in parallel
let out1 = thread::spawn(|| self.node1.process(intermediate1));
let out2 = thread::spawn(|| self.node2.process(intermediate2));
(out1.join().unwrap(), out2.join().unwrap())
}
}
but this doesn't work and says everything must be sent through threads safely. I don't think that sounds right, is this the wrong way to do it? The problem then becomes that I need a &mut for node1 and a &mut for node2 on each thread. Is there a good way to do this without cloning?