Function permutator::combination_cell
source · [−]pub fn combination_cell<'a, T>(
domain: &'a [T],
r: usize,
result: Rc<RefCell<&'a mut [&'a T]>>,
cb: impl FnMut()
)
Expand description
Deprecated
See combination function for reason of deprecation
Similar to combination function except the way it return the combination. It return result through Rc<RefCell<>> to mutable slice of result. It’ll notify caller on each new result via empty callback function.
Parameters
domain
A raw data to get combination.r
A size of each combination.result
An Rc<RefCell<>> to mutable slice of length equals tor
cb
A callback function which will be called after new combination inresult
is set.
Return
This function return result through function’s parameter result
and
notify caller that new result is available through cb
callback function.
Rationale
The safe combination function return value in callback parameter. It limit the lifetime of return combination to be valid only inside it callback. To use it outside callback scope, it need to copy the value which will have performance penalty. Therefore, jeopardize it own goal of being fast. This function provide alternative safe way to share result which is roughly 50% slower to unsafe counterpart. The performance is on par with using GosperCombinationIterator with next_into_cell function.
Example
The scenario is we want to get combination from single source of data then distribute the combination to two workers which read each combination then do something about it, which in this example, simply print it.
use permutator::combination_cell;
use std::fmt::Debug;
use std::rc::Rc;
use std::cell::RefCell;
// define a trait that represent a data consumer
trait Consumer {
fn consume(&self); // cannot mut data because rule of no more than 1 ref mut at a time.
}
struct Worker1<'a, T : 'a> {
data : Rc<RefCell<&'a mut[&'a T]>> // A reference to each combination
}
impl<'a, T : 'a + Debug> Consumer for Worker1<'a, T> {
fn consume(&self) {
// Read data then do something about it. In this case, simply print it.
println!("Work1 has {:?}", self.data.borrow());
}
}
struct Worker2<'a, T : 'a> {
data : Rc<RefCell<&'a mut[&'a T]>> // A reference to each combination
}
impl<'a, T : 'a + Debug> Consumer for Worker2<'a, T> {
fn consume(&self) {
// Read data then do something about it. In this case, simply print it.
println!("Work2 has {:?}", self.data.borrow());
}
}
fn start_combination_process<'a>(data : &'a[i32], cur_result : Rc<RefCell<&'a mut[&'a i32]>>, k : usize, consumers : Vec<Box<Consumer + 'a>>) {
combination_cell(data, k, cur_result, || {
consumers.iter().for_each(|c| {
c.consume();
})
});
}
let k = 3;
let data = &[1, 2, 3, 4, 5];
let mut result = vec![&data[0]; k];
let shared = Rc::new(RefCell::new(result.as_mut_slice()));
let worker1 = Worker1 {
data : Rc::clone(&shared)
};
let worker2 = Worker2 {
data : Rc::clone(&shared)
};
let consumers : Vec<Box<Consumer>> = vec![Box::new(worker1), Box::new(worker2)];
start_combination_process(data, shared, k, consumers);