atomic_ref_box/
lib.rs

1use std::marker::PhantomData;
2use std::ops::{Deref, DerefMut};
3use std::sync::{Arc, RwLock, Weak};
4
5//
6// Atomic Reference Box
7//
8
9/// A thread-safe pointer type that uniquely owns a heap allocation of type T,
10/// but allows immutable (weak) references to be created and shared.
11///
12/// CRITICAL:
13/// The current implementation is flawed. See Deref implementation for reason.
14pub struct AtomicRefBox<T> {
15    inner: Arc<Inner<T>>,
16}
17
18impl<T> AtomicRefBox<T> {
19    pub fn new(value: T) -> AtomicRefBox<T> {
20        AtomicRefBox {
21            inner: Arc::new(Inner {
22                lock: RwLock::new(Some(value)),
23            }),
24        }
25    }
26
27    /// Immutably borrows the inner value.
28    pub fn borrow(this: &Self) -> AtomicRef<T> {
29        todo!()
30    }
31
32    /// Mutably borrows the inner value.
33    pub fn borrow_mut(this: &Self) -> AtomicMutRef<T> {
34        // Similar problem as directly deref-ing + extra issues:
35        // When a mutable reference is produced, the weak references
36        // should not be able to borrow until the mutable reference is dropped
37        // This logically involves somehow holding onto the write lock until
38        // the mutable reference is dropped (how to detect this?)
39        todo!()
40    }
41
42    pub fn to_weak(this: &Self) -> AtomicWeakRef<T> {
43        AtomicWeakRef::new(Arc::downgrade(&this.inner))
44    }
45
46    /// Extracts the inner value from the box.
47    ///
48    /// This function may block until all weak references
49    /// have finished actively borrowing the value.
50    pub fn into_inner(this: Self) -> T {
51        this.inner.lock.write().unwrap().take().unwrap()
52    }
53}
54
55impl<T> Deref for AtomicRefBox<T> {
56    type Target = T;
57
58    fn deref(&self) -> &Self::Target {
59        // When using a RwLock, this method cannot be implemented
60        // without acquiring a read lock.
61        // But when the inner value is returned, the lock is released
62        // and a lifetime error occurs
63        todo!()
64    }
65}
66
67impl<T> AsRef<T> for AtomicRefBox<T> {
68    fn as_ref(&self) -> &T {
69        &**self
70    }
71}
72
73struct Inner<T> {
74    lock: RwLock<Option<T>>,
75}
76
77//
78// Atomic Immutable Reference
79//
80
81pub struct AtomicRef<'a, T> {
82    marker: PhantomData<&'a mut T>, // TODO temp
83}
84
85impl<'a, T> Deref for AtomicRef<'a, T> {
86    type Target = T;
87
88    fn deref(&self) -> &Self::Target {
89        todo!()
90    }
91}
92
93//
94// Atomic Mutable Reference
95//
96
97pub struct AtomicMutRef<'a, T> {
98    marker: PhantomData<&'a mut T>, // TODO temp
99}
100
101impl<'a, T> Deref for AtomicMutRef<'a, T> {
102    type Target = T;
103
104    fn deref(&self) -> &Self::Target {
105        todo!()
106    }
107}
108
109impl<'a, T> DerefMut for AtomicMutRef<'a, T> {
110    fn deref_mut(&mut self) -> &mut Self::Target {
111        todo!()
112    }
113}
114
115//
116// Atomic Weak Reference
117//
118
119pub struct AtomicWeakRef<T> {
120    weak: Weak<Inner<T>>,
121}
122
123impl<T> AtomicWeakRef<T> {
124    fn new(weak: Weak<Inner<T>>) -> AtomicWeakRef<T> {
125        AtomicWeakRef { weak }
126    }
127
128    pub fn borrow<R>(&self, op: impl FnOnce(&T) -> R) -> Option<R> {
129        let Some(w) = self.weak.upgrade() else {
130            return None;
131        };
132        let read_binding = w.lock.read().unwrap();
133        let Some(t) = read_binding.deref() else {
134            return None;
135        };
136        Some(op(t))
137    }
138}