#[derive(Debug, Clone, Default)]
struct SafeCell<T> {
inner: T,
}
impl<T> SafeCell<T> {
fn get(&self) -> &T {
return &self.inner;
}
fn get_mut(&mut self) -> &mut T {
return &mut self.inner;
}
fn into_inner(self) -> T {
return self.inner;
}
fn new(value: T) -> Self {
return SafeCell {
inner: value,
};
}
}
#[cfg(test)]
mod tests {
use std::thread;
use std::sync::{Arc, Mutex};
use super::*;
#[test]
fn basic() {
let mut cell = SafeCell::new(0);
assert_eq!(cell.get(), &0);
*cell.get_mut() += 1;
assert_eq!(cell.get(), &1);
let mut other_cell = cell.clone();
*other_cell.get_mut() += 1;
assert_eq!(other_cell.get(), &2);
assert_eq!(cell.get(), &1);
assert_eq!(cell.into_inner(), 1);
}
#[test]
fn share() {
let cell = Arc::new(Mutex::new(SafeCell::new(0)));
let copy = cell.clone();
let lock = cell.lock().unwrap();
let a = {
let cell = copy.clone();
thread::spawn(move || {
for _ in 0..10 {
*cell.lock().unwrap().get_mut() += 1;
}
})
};
let b = {
let cell = copy.clone();
thread::spawn(move || {
for _ in 0..10 {
*cell.lock().unwrap().get_mut() += 2;
}
})
};
assert_eq!(lock.get(), &0);
drop(lock);
a.join().unwrap();
b.join().unwrap();
assert_eq!(cell.lock().unwrap().get(), &30);
}
}