use std::sync::Arc;
use crate::option::OptionCell;
#[derive(Clone)]
pub struct Writer<T> {
cell: Arc<OptionCell<T>>
}
impl<T> Writer<T> {
fn new(cell: Arc<OptionCell<T>>) -> Self {
Self {
cell,
}
}
pub fn write(&self, val: T) {
self.cell.replace(val);
}
}
pub struct Reader<T> {
cell: Arc<OptionCell<T>>,
val: T
}
impl<T> Reader<T> {
fn new(cell: Arc<OptionCell<T>>) -> Self {
Self {
val: cell.take().unwrap(),
cell,
}
}
pub fn writer(&self) -> Writer<T> {
Writer::new(self.cell.clone())
}
pub fn read_with_is_new(&mut self) -> (&T, bool) {
match self.cell.take() {
None => (&self.val, false),
Some(val) => {
self.val = val;
(&self.val, true)
}
}
}
pub fn read(&mut self) -> &T {
match self.cell.take() {
None => &self.val,
Some(val) => {
self.val = val;
&self.val
}
}
}
}
pub fn new<T>(val: T) -> (Writer<T>, Reader<T>) {
let cell = Arc::new(OptionCell::new(val));
(Writer::new(cell.clone()), Reader::new(cell))
}
pub fn default<T>() -> (Writer<T>, Reader<T>)
where
T: Default
{
let cell = Arc::new(OptionCell::new(T::default()));
(Writer::new(cell.clone()), Reader::new(cell))
}
#[cfg(test)]
mod test {
use crate::mpsc;
#[test]
fn test_read() {
let (w, mut r) = mpsc::new(vec!["fffff"; 1000]);
assert_eq!(r.read(), &vec!["fffff"; 1000]);
w.write(vec!["Not good, but ok"]);
assert_eq!(r.read(), &vec!["Not good, but ok"]);
}
#[test]
fn test_read_with_is_new() {
let (w, mut r) = mpsc::new(vec!["fffff"; 1000]);
assert_eq!(r.read_with_is_new(), (&vec!["fffff"; 1000], false));
w.write(vec!["Not good"]);
assert_eq!(r.read_with_is_new(), (&vec!["Not good"], true));
}
#[test]
fn is_work() {
let (w0, mut r) = mpsc::new(vec!["Ukraine"; 1000]);
let w1 = r.writer();
let w2 = r.writer();
let w3 = r.writer();
let w4 = r.writer();
let w5 = r.writer();
std::thread::spawn(move || loop {
w0.write(vec!["Slovakia"; 1001])
});
std::thread::spawn(move || loop {
w1.write(vec!["Estonia"; 1002])
});
std::thread::spawn(move || loop {
w2.write(vec!["Czechia"; 1003])
});
std::thread::spawn(move || loop {
w3.write(vec!["United Kingdom"; 1004])
});
std::thread::spawn(move || loop {
w4.write(vec!["Lithuania"; 1004])
});
std::thread::spawn(move || loop {
w5.write(vec!["Latvia"; 1004])
});
let mut slovakia = 0;
let mut estonia = 0;
let mut czechia = 0;
let mut united_kingdom = 0;
let mut lithuania = 0;
let mut latvia = 0;
let mut ukraine = 0;
for _ in 0..10000000usize {
match r.read() {
val if val.first() == Some(&"Slovakia") => slovakia += 1,
val if val.first() == Some(&"Estonia") => estonia += 1,
val if val.first() == Some(&"Czechia") => czechia += 1,
val if val.first() == Some(&"United Kingdom") => united_kingdom += 1,
val if val.first() == Some(&"Lithuania") => lithuania += 1,
val if val.first() == Some(&"Latvia") => latvia += 1,
val if val.first() == Some(&"Ukraine") => ukraine += 1,
val => println!("val: {:?}, Not good, but ok", val.first())
}
}
println!("count Slovakia: {}", slovakia);
println!("count Estonia: {}", estonia);
println!("count Czechia: {}", czechia);
println!("count United Kingdom: {}", united_kingdom);
println!("count Lithuania: {}", lithuania);
println!("count Latvia: {}", latvia);
println!("count Ukraine: {}", ukraine);
}
}