shadow_shim_helper_rs/rootedcell/
rc.rs

1use std::{
2    cell::{Cell, UnsafeCell},
3    ptr::NonNull,
4};
5
6use crate::explicit_drop::ExplicitDrop;
7
8use super::{Root, Tag};
9
10struct RootedRcInternal<T> {
11    val: UnsafeCell<Option<T>>,
12    strong_count: Cell<u32>,
13    weak_count: Cell<u32>,
14}
15
16impl<T> RootedRcInternal<T> {
17    pub fn new(val: T) -> Self {
18        Self {
19            val: UnsafeCell::new(Some(val)),
20            strong_count: Cell::new(1),
21            weak_count: Cell::new(0),
22        }
23    }
24
25    pub fn inc_strong(&self) {
26        self.strong_count.set(self.strong_count.get() + 1)
27    }
28
29    pub fn dec_strong(&self) {
30        self.strong_count.set(self.strong_count.get() - 1)
31    }
32
33    pub fn inc_weak(&self) {
34        self.weak_count.set(self.weak_count.get() + 1)
35    }
36
37    pub fn dec_weak(&self) {
38        self.weak_count.set(self.weak_count.get() - 1)
39    }
40}
41
42enum RefType {
43    Weak,
44    Strong,
45}
46
47// Shared implementation for strong and weak references
48struct RootedRcCommon<T> {
49    tag: Tag,
50    internal: Option<NonNull<RootedRcInternal<T>>>,
51}
52
53impl<T> RootedRcCommon<T> {
54    pub fn new(root: &Root, val: T) -> Self {
55        Self {
56            tag: root.tag(),
57            internal: Some(
58                NonNull::new(Box::into_raw(Box::new(RootedRcInternal::new(val)))).unwrap(),
59            ),
60        }
61    }
62
63    // Validates that no other thread currently has access to self.internal, and
64    // return a reference to it.
65    pub fn borrow_internal(&self, root: &Root) -> &RootedRcInternal<T> {
66        assert_eq!(
67            root.tag, self.tag,
68            "Tried using root {:?} instead of {:?}",
69            root.tag, self.tag
70        );
71        // SAFETY:
72        // * Holding a reference to `root` proves no other threads can currently
73        //   access `self.internal`.
74        // * `self.internal` is accessible since we hold a strong reference.
75        unsafe { self.internal.unwrap().as_ref() }
76    }
77
78    /// Decrement the reference. If this was the last strong reference, return the value.
79    pub fn safely_drop(mut self, root: &Root, t: RefType) -> Option<T> {
80        let internal: &RootedRcInternal<T> = self.borrow_internal(root);
81        match t {
82            RefType::Weak => internal.dec_weak(),
83            RefType::Strong => internal.dec_strong(),
84        };
85        let strong_count = internal.strong_count.get();
86        let weak_count = internal.weak_count.get();
87
88        // If there are no more strong references, prepare to drop the value.
89        // If the value was already dropped (e.g. because we're now dropping a
90        // weak reference after all the strong refs were already dropped), this
91        // is a no-op.
92        let val: Option<T> = if strong_count == 0 {
93            // SAFETY: Since no strong references remain, nothing else can be
94            // referencing the internal value.
95            unsafe { internal.val.get().as_mut().unwrap().take() }
96        } else {
97            None
98        };
99
100        // Clear `self.internal`, so that `drop` knows that `safely_drop` ran.
101        let internal: NonNull<RootedRcInternal<T>> = self.internal.take().unwrap();
102
103        // If there are neither strong nor weak references, drop `internal` itself.
104        if strong_count == 0 && weak_count == 0 {
105            // SAFETY: We know the pointer is still valid since we had the last
106            // reference, and since the counts are now zero, there can be no
107            // other references.
108            drop(unsafe { Box::from_raw(internal.as_ptr()) });
109        }
110
111        val
112    }
113
114    pub fn clone(&self, root: &Root, t: RefType) -> Self {
115        let internal: &RootedRcInternal<T> = self.borrow_internal(root);
116        match t {
117            RefType::Weak => internal.inc_weak(),
118            RefType::Strong => internal.inc_strong(),
119        };
120        Self {
121            tag: self.tag,
122            internal: self.internal,
123        }
124    }
125}
126
127impl<T> Drop for RootedRcCommon<T> {
128    #[inline]
129    fn drop(&mut self) {
130        if self.internal.is_some() {
131            // `explicit_drop` is the public interface for the internal `safely_drop`
132            log::error!("Dropped without calling `explicit_drop`");
133
134            // We *can* continue without violating Rust safety properties; the
135            // underlying object will just be leaked, since the ref count will
136            // never reach zero.
137            //
138            // If we're not already panicking, it's useful to panic here to make
139            // the leak more visible.
140            //
141            // If we are already panicking though, that may already explain how
142            // a call to `safely_drop` got skipped, and panicking again would
143            // just obscure the original panic.
144            #[cfg(debug_assertions)]
145            if !std::thread::panicking() {
146                panic!("Dropped without calling `explicit_drop`");
147            }
148        }
149    }
150}
151
152// SAFETY: RootedRcCommon ensures that its internals can only be accessed when
153// the Root is held by the current thread, effectively synchronizing the
154// reference count.
155unsafe impl<T: Sync + Send> Send for RootedRcCommon<T> {}
156unsafe impl<T: Sync + Send> Sync for RootedRcCommon<T> {}
157
158/// Analagous to [std::rc::Rc]. In particular like [std::rc::Rc] and unlike
159/// [std::sync::Arc], it doesn't perform any atomic operations internally,
160/// making it relatively inexpensive
161///
162/// Unlike [std::rc::Rc], this type [Send] and [Sync] if `T` is. This is safe because
163/// the owner is required to prove ownership of the associated [Root]
164/// to perform any sensitive operations.
165///
166/// Instances must be destroyed explicitly, using [`RootedRc::explicit_drop`],
167/// [`RootedRc::explicit_drop_recursive`], or [`RootedRc::into_inner`].  These
168/// validate that the [Root] is held before manipulating reference counts, etc.
169///
170/// Dropping `RootedRc` without calling one of these methods results in a
171/// `panic` in debug builds, or leaking the object in release builds.
172pub struct RootedRc<T> {
173    common: RootedRcCommon<T>,
174}
175
176impl<T> RootedRc<T> {
177    /// Creates a new object associated with `root`.
178    #[inline]
179    pub fn new(root: &Root, val: T) -> Self {
180        Self {
181            common: RootedRcCommon::new(root, val),
182        }
183    }
184
185    /// Create a weak reference.
186    ///
187    /// We use fully qualified syntax here for consistency with Rc and Arc and
188    /// to avoid name conflicts with `T`'s methods.
189    #[inline]
190    pub fn downgrade(this: &Self, root: &Root) -> RootedRcWeak<T> {
191        RootedRcWeak {
192            common: this.common.clone(root, RefType::Weak),
193        }
194    }
195
196    /// Like [Clone::clone], but requires that the corresponding Root is held.
197    ///
198    /// Intentionally named clone to shadow Self::deref()::clone().
199    ///
200    /// Panics if `root` is not the associated [Root].
201    #[inline]
202    pub fn clone(&self, root: &Root) -> Self {
203        Self {
204            common: self.common.clone(root, RefType::Strong),
205        }
206    }
207
208    /// Drop the `RootedRc`, and return the inner value if this was the last
209    /// strong reference.
210    #[inline]
211    pub fn into_inner(this: Self, root: &Root) -> Option<T> {
212        this.common.safely_drop(root, RefType::Strong)
213    }
214
215    /// Drops `self`, and if `self` was the last strong reference, call
216    /// `ExplicitDrop::explicit_drop` on the internal value.
217    pub fn explicit_drop_recursive(
218        self,
219        root: &Root,
220        param: &T::ExplicitDropParam,
221    ) -> Option<T::ExplicitDropResult>
222    where
223        T: ExplicitDrop,
224    {
225        Self::into_inner(self, root).map(|val| val.explicit_drop(param))
226    }
227}
228
229impl<T> ExplicitDrop for RootedRc<T> {
230    type ExplicitDropParam = Root;
231
232    type ExplicitDropResult = ();
233
234    /// If T itself implements `ExplicitDrop`, consider
235    /// `RootedRc::explicit_drop_recursive` instead to call it when dropping the
236    /// last strong reference.
237    fn explicit_drop(self, root: &Self::ExplicitDropParam) -> Self::ExplicitDropResult {
238        self.common.safely_drop(root, RefType::Strong);
239    }
240}
241
242impl<T> std::ops::Deref for RootedRc<T> {
243    type Target = T;
244
245    #[inline]
246    fn deref(&self) -> &Self::Target {
247        // No need to require a reference to `Root` here since we're not
248        // touching the counts, only the value itself, which we already required
249        // to be Sync and Send for RootedRc<T> to be Sync and Send.
250
251        // SAFETY: Pointer to `internal` is valid, since we hold a strong ref.
252        let internal = unsafe { self.common.internal.unwrap().as_ref() };
253
254        // SAFETY: Since we hold a strong ref, we know that `val` is valid, and
255        // that there are no mutable references to it. (The only time we create
256        // a mutable reference is to drop the T value when the strong ref count
257        // reaches zero)
258        let val = unsafe { &*internal.val.get() };
259        val.as_ref().unwrap()
260    }
261}
262
263#[cfg(test)]
264mod test_rooted_rc {
265    use std::{sync::Arc, thread};
266
267    use super::*;
268
269    #[test]
270    fn construct_and_drop() {
271        let root = Root::new();
272        let rc = RootedRc::new(&root, 0);
273        rc.explicit_drop(&root)
274    }
275
276    #[test]
277    #[cfg(debug_assertions)]
278    #[should_panic]
279    fn drop_without_lock_panics_with_debug_assertions() {
280        let root = Root::new();
281        drop(RootedRc::new(&root, 0));
282    }
283
284    #[test]
285    #[cfg(not(debug_assertions))]
286    fn drop_without_lock_leaks_without_debug_assertions() {
287        let root = Root::new();
288        let rc = std::rc::Rc::new(());
289        let rrc = RootedRc::new(&root, rc.clone());
290        drop(rrc);
291        // Because we didn't call `explicit_drop`, RootedRc can't safely call the
292        // inner rc's Drop. Instead of panicking, we just leak it.
293        assert_eq!(std::rc::Rc::strong_count(&rc), 2);
294    }
295
296    #[test]
297    fn send_to_worker_thread() {
298        let root = Root::new();
299        let rc = RootedRc::new(&root, 0);
300        thread::spawn(move || {
301            // Can access immutably
302            let _ = *rc + 2;
303            // Need to explicitly drop, since it mutates refcount.
304            rc.explicit_drop(&root)
305        })
306        .join()
307        .unwrap();
308    }
309
310    #[test]
311    fn send_to_worker_thread_and_retrieve() {
312        let root = Root::new();
313        let root = thread::spawn(move || {
314            let rc = RootedRc::new(&root, 0);
315            rc.explicit_drop(&root);
316            root
317        })
318        .join()
319        .unwrap();
320        let rc = RootedRc::new(&root, 0);
321        rc.explicit_drop(&root)
322    }
323
324    #[test]
325    fn clone_to_worker_thread() {
326        let root = Root::new();
327        let rc = RootedRc::new(&root, 0);
328
329        // Create a clone of rc that we'll pass to worker thread.
330        let rc_thread = rc.clone(&root);
331
332        // Worker takes ownership of rc_thread and root;
333        // Returns ownership of root.
334        let root = thread::spawn(move || {
335            let _ = *rc_thread;
336            rc_thread.explicit_drop(&root);
337            root
338        })
339        .join()
340        .unwrap();
341
342        // Take the lock to drop rc
343        rc.explicit_drop(&root);
344    }
345
346    #[test]
347    fn threads_contend_over_lock() {
348        let root = Arc::new(std::sync::Mutex::new(Root::new()));
349        let rc = RootedRc::new(&root.lock().unwrap(), 0);
350
351        let threads: Vec<_> = (0..100)
352            .map(|_| {
353                // Create a clone of rc that we'll pass to worker thread.
354                let rc = rc.clone(&root.lock().unwrap());
355                let root = root.clone();
356
357                thread::spawn(move || {
358                    let rootlock = root.lock().unwrap();
359                    let rc2 = rc.clone(&rootlock);
360                    rc.explicit_drop(&rootlock);
361                    rc2.explicit_drop(&rootlock);
362                })
363            })
364            .collect();
365
366        for handle in threads {
367            handle.join().unwrap();
368        }
369
370        rc.explicit_drop(&root.lock().unwrap());
371    }
372
373    #[test]
374    fn into_inner_recursive() {
375        let root = Root::new();
376        let inner = RootedRc::new(&root, ());
377        let outer1 = RootedRc::new(&root, inner);
378        let outer2 = outer1.clone(&root);
379
380        // Dropping the first outer returns None, since there is still another strong ref.
381        assert!(RootedRc::into_inner(outer1, &root).is_none());
382
383        // Dropping the second outer returns the inner ref.
384        let inner = RootedRc::into_inner(outer2, &root).unwrap();
385
386        // Now we can safely drop the inner ref.
387        inner.explicit_drop(&root);
388    }
389
390    #[test]
391    fn explicit_drop() {
392        let root = Root::new();
393        let rc = RootedRc::new(&root, ());
394        rc.explicit_drop(&root);
395    }
396
397    #[test]
398    fn explicit_drop_recursive() {
399        // Defining `ExplicitDrop` for `MyOuter` lets us use `RootedRc::explicit_drop_recursive`
400        // to safely drop the inner `RootedRc` when dropping a `RootedRc<MyOuter>`.
401        struct MyOuter(RootedRc<()>);
402        impl ExplicitDrop for MyOuter {
403            type ExplicitDropParam = Root;
404            type ExplicitDropResult = ();
405
406            fn explicit_drop(self, root: &Self::ExplicitDropParam) -> Self::ExplicitDropResult {
407                self.0.explicit_drop(root);
408            }
409        }
410
411        let root = Root::new();
412        let inner = RootedRc::new(&root, ());
413        let outer1 = RootedRc::new(&root, MyOuter(inner));
414        let outer2 = RootedRc::new(&root, MyOuter(outer1.0.clone(&root)));
415        outer1.explicit_drop_recursive(&root, &root);
416        outer2.explicit_drop_recursive(&root, &root);
417    }
418}
419
420pub struct RootedRcWeak<T> {
421    common: RootedRcCommon<T>,
422}
423
424impl<T> RootedRcWeak<T> {
425    #[inline]
426    pub fn upgrade(&self, root: &Root) -> Option<RootedRc<T>> {
427        let internal = self.common.borrow_internal(root);
428
429        if internal.strong_count.get() == 0 {
430            return None;
431        }
432
433        Some(RootedRc {
434            common: self.common.clone(root, RefType::Strong),
435        })
436    }
437
438    /// Like [Clone::clone], but requires that the corresponding Root is held.
439    ///
440    /// Intentionally named clone to shadow Self::deref()::clone().
441    ///
442    /// Panics if `root` is not the associated [Root].
443    #[inline]
444    pub fn clone(&self, root: &Root) -> Self {
445        Self {
446            common: self.common.clone(root, RefType::Weak),
447        }
448    }
449}
450
451impl<T> ExplicitDrop for RootedRcWeak<T> {
452    type ExplicitDropParam = Root;
453
454    type ExplicitDropResult = ();
455
456    #[inline]
457    fn explicit_drop(self, root: &Self::ExplicitDropParam) -> Self::ExplicitDropResult {
458        let val = self.common.safely_drop(root, RefType::Weak);
459        // Since this isn't a strong reference, this can't be the *last* strong
460        // reference, so the value should never be returned.
461        debug_assert!(val.is_none());
462    }
463}
464
465// SAFETY: RootedRc ensures that its internals can only be accessed when the
466// Root is held by the current thread, effectively synchronizing the reference
467// count.
468unsafe impl<T: Sync + Send> Send for RootedRcWeak<T> {}
469unsafe impl<T: Sync + Send> Sync for RootedRcWeak<T> {}
470
471#[cfg(test)]
472mod test_rooted_rc_weak {
473    use super::*;
474
475    #[test]
476    fn successful_upgrade() {
477        let root = Root::new();
478        let strong = RootedRc::new(&root, 42);
479        let weak = RootedRc::downgrade(&strong, &root);
480
481        let upgraded = weak.upgrade(&root).unwrap();
482
483        assert_eq!(*upgraded, *strong);
484
485        upgraded.explicit_drop(&root);
486        weak.explicit_drop(&root);
487        strong.explicit_drop(&root);
488    }
489
490    #[test]
491    fn failed_upgrade() {
492        let root = Root::new();
493        let strong = RootedRc::new(&root, 42);
494        let weak = RootedRc::downgrade(&strong, &root);
495
496        strong.explicit_drop(&root);
497
498        assert!(weak.upgrade(&root).is_none());
499
500        weak.explicit_drop(&root);
501    }
502
503    #[test]
504    #[cfg(debug_assertions)]
505    #[should_panic]
506    fn drop_without_lock_panics_with_debug_assertions() {
507        let root = Root::new();
508        let strong = RootedRc::new(&root, 42);
509        drop(RootedRc::downgrade(&strong, &root));
510        strong.explicit_drop(&root);
511    }
512
513    // Validate that circular references are cleaned up correctly.
514    #[test]
515    fn circular_reference() {
516        std::thread_local! {
517            static THREAD_ROOT: Root = Root::new();
518        }
519
520        struct MyStruct {
521            // Circular reference
522            weak_self: Cell<Option<RootedRcWeak<Self>>>,
523        }
524        impl MyStruct {
525            fn new() -> RootedRc<Self> {
526                THREAD_ROOT.with(|root| {
527                    let rv = RootedRc::new(
528                        root,
529                        MyStruct {
530                            weak_self: Cell::new(None),
531                        },
532                    );
533                    let weak = RootedRc::downgrade(&rv, root);
534                    rv.weak_self.set(Some(weak));
535                    rv
536                })
537            }
538        }
539        impl Drop for MyStruct {
540            fn drop(&mut self) {
541                let weak = self.weak_self.replace(None).unwrap();
542                THREAD_ROOT.with(|root| {
543                    weak.explicit_drop(root);
544                });
545            }
546        }
547
548        let val = MyStruct::new();
549        THREAD_ROOT.with(|root| {
550            val.explicit_drop(root);
551        })
552    }
553
554    #[test]
555    #[cfg(not(debug_assertions))]
556    fn drop_without_lock_doesnt_leak_value() {
557        let root = Root::new();
558        let rc = std::rc::Rc::new(());
559        let strong = RootedRc::new(&root, rc.clone());
560        drop(RootedRc::downgrade(&strong, &root));
561        strong.explicit_drop(&root);
562
563        // Because we safely dropped all of the strong references,
564        // the internal std::rc::Rc value should still have been dropped.
565        // The `internal` field itself will be leaked since the weak count
566        // never reaches 0.
567        assert_eq!(std::rc::Rc::strong_count(&rc), 1);
568    }
569}