Hi,
I've recently come across a memory access requirement for one of my pet projects:
- Concurrent field read and write access across multiple threads.
- No Mutex / RwLock
- Writes don't need to be reflected in current readers holding a reference to that field.
- No need to worry about concurrent writes (i.e. read update interleaving)
- No external mutability ('&mut')
So is basically a GC'ed like semantics - you get a reference to that field if someone replaces it with some new instance you will still be holding the 'old' value, and that's fine.
Since this is my first time using unsafe and pointers I would like to know if I'm missing something or perhaps doing something that's unnecessary ? mainly regarding correctness and not speed.
Is Box
necessary here?
struct Container<T> {
item: AtomicPtr<Rc<T>>,
}
impl<T> Container<T> {
pub fn new(item: T) -> Self {
let r = Self::box_leak(item);
Self {
item: AtomicPtr::new(r),
}
}
fn box_leak<'a>(item: T) -> &'a mut Rc<T> {
Box::leak(Box::new(Rc::new(item)))
}
pub fn replace(&self, new: T) {
let r = Self::box_leak(new);
let old = self.item.swap(r, Ordering::SeqCst);
let oldbox = unsafe { Box::from_raw(old) };
drop(oldbox); //just being explict
}
pub fn get(&self) -> Rc<T> {
let ptr = self.item.load(Ordering::SeqCst);
return unsafe { (*ptr).clone() };
}
}
impl<T> Drop for Container<T> {
fn drop(&mut self) {
let old = self.item.load(Ordering::SeqCst);
let oldbox = unsafe { Box::from_raw(old) };
drop(oldbox); //just being explict
}
}
Thank you