summary refs log tree commit diff
path: root/library/alloc/src
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2021-04-07 13:07:06 +0200
committerGitHub <noreply@github.com>2021-04-07 13:07:06 +0200
commit505846ec07c1303369358a1c3358c7d7ee0ca12e (patch)
tree54841e777a4af849b43003dcdb19b4e22e781a17 /library/alloc/src
parent1c158b6a8b440f826d952c3a8f42bdc3f77a5ac1 (diff)
parenta591d7ab9004f5b653b6f135c4a79bd3104a44a4 (diff)
downloadrust-505846ec07c1303369358a1c3358c7d7ee0ca12e.tar.gz
rust-505846ec07c1303369358a1c3358c7d7ee0ca12e.zip
Rollup merge of #83476 - mystor:rc_mutate_strong_count, r=m-ou-se
Add strong_count mutation methods to Rc

The corresponding methods were stabilized on `Arc` in #79285 (tracking: #71983). This patch implements and stabilizes identical methods on the `Rc` types as well.
Diffstat (limited to 'library/alloc/src')
-rw-r--r--library/alloc/src/rc.rs67
1 files changed, 67 insertions, 0 deletions
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 2ee5e6c791c..c81ababf151 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -910,6 +910,73 @@ impl<T: ?Sized> Rc<T> {
         this.inner().strong()
     }
 
+    /// Increments the strong reference count on the `Rc<T>` associated with the
+    /// provided pointer by one.
+    ///
+    /// # Safety
+    ///
+    /// The pointer must have been obtained through `Rc::into_raw`, and the
+    /// associated `Rc` instance must be valid (i.e. the strong count must be at
+    /// least 1) for the duration of this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::rc::Rc;
+    ///
+    /// let five = Rc::new(5);
+    ///
+    /// unsafe {
+    ///     let ptr = Rc::into_raw(five);
+    ///     Rc::increment_strong_count(ptr);
+    ///
+    ///     let five = Rc::from_raw(ptr);
+    ///     assert_eq!(2, Rc::strong_count(&five));
+    /// }
+    /// ```
+    #[inline]
+    #[stable(feature = "rc_mutate_strong_count", since = "1.53.0")]
+    pub unsafe fn increment_strong_count(ptr: *const T) {
+        // Retain Rc, but don't touch refcount by wrapping in ManuallyDrop
+        let rc = unsafe { mem::ManuallyDrop::new(Rc::<T>::from_raw(ptr)) };
+        // Now increase refcount, but don't drop new refcount either
+        let _rc_clone: mem::ManuallyDrop<_> = rc.clone();
+    }
+
+    /// Decrements the strong reference count on the `Rc<T>` associated with the
+    /// provided pointer by one.
+    ///
+    /// # Safety
+    ///
+    /// The pointer must have been obtained through `Rc::into_raw`, and the
+    /// associated `Rc` instance must be valid (i.e. the strong count must be at
+    /// least 1) when invoking this method. This method can be used to release
+    /// the final `Rc` and backing storage, but **should not** be called after
+    /// the final `Rc` has been released.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::rc::Rc;
+    ///
+    /// let five = Rc::new(5);
+    ///
+    /// unsafe {
+    ///     let ptr = Rc::into_raw(five);
+    ///     Rc::increment_strong_count(ptr);
+    ///
+    ///     let five = Rc::from_raw(ptr);
+    ///     assert_eq!(2, Rc::strong_count(&five));
+    ///     Rc::decrement_strong_count(ptr);
+    ///     assert_eq!(1, Rc::strong_count(&five));
+    /// }
+    /// ```
+    #[inline]
+    #[stable(feature = "rc_mutate_strong_count", since = "1.53.0")]
+    pub unsafe fn decrement_strong_count(ptr: *const T) {
+        unsafe { mem::drop(Rc::from_raw(ptr)) };
+    }
+
     /// Returns `true` if there are no other `Rc` or [`Weak`] pointers to
     /// this allocation.
     #[inline]