From: Joshua Simmons Date: Fri, 11 Nov 2022 23:02:58 +0000 (+0100) Subject: Fix `Arc` incorrectly initializing itself as `Rc` X-Git-Url: https://git.nega.tv//gitweb.cgi?a=commitdiff_plain;h=7cae633b29a3500eb88400624c58435357464530;p=josh%2Fnarcissus Fix `Arc` incorrectly initializing itself as `Rc` --- diff --git a/narcissus-core/src/ref_count.rs b/narcissus-core/src/ref_count.rs index 5408b35..35ea1d2 100644 --- a/narcissus-core/src/ref_count.rs +++ b/narcissus-core/src/ref_count.rs @@ -21,6 +21,14 @@ impl Inner { value, } } + + #[inline] + fn new_atomic(value: T) -> Self { + Self { + strong: AtomicI32::new(1), + value, + } + } } impl Inner { @@ -188,7 +196,7 @@ unsafe impl Sync for Arc {} impl Arc { pub fn new(value: T) -> Self { - Self::from_inner(Box::leak(Box::new(Inner::new(value))).into()) + Self::from_inner(Box::leak(Box::new(Inner::new_atomic(value))).into()) } } @@ -301,6 +309,28 @@ impl Deref for Arc { mod tests { use crate::*; + #[test] + fn rc_drop() { + use std::sync::atomic::{AtomicU32, Ordering}; + + struct A<'a>(&'a AtomicU32); + impl<'a> Drop for A<'a> { + fn drop(&mut self) { + self.0.fetch_add(1, Ordering::SeqCst); + } + } + + let counter = AtomicU32::new(0); + let a = Arc::new(A(&counter)); + assert_eq!(counter.load(Ordering::Relaxed), 0); + let b = a.clone(); + assert_eq!(counter.load(Ordering::Relaxed), 0); + drop(a); + assert_eq!(counter.load(Ordering::Relaxed), 0); + drop(b); + assert_eq!(counter.load(Ordering::Relaxed), 1); + } + #[test] fn rc_double_upgrade() { let rc1 = Rc::new(());