diff options
| author | Dylan DPC <dylan.dpc@gmail.com> | 2020-05-07 21:46:06 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-05-07 21:46:06 +0200 |
| commit | 5e9b3720e5c49656b78a047922bbc34fe74a67b3 (patch) | |
| tree | ef2d032fd29a4102f02e5c9e4dc841e191b38b74 /src/liballoc/sync.rs | |
| parent | a08c47310c7d49cbdc5d7afb38408ba519967ecd (diff) | |
| parent | b04599ff8405d476a05b83839c67e9aea3c640cb (diff) | |
| download | rust-5e9b3720e5c49656b78a047922bbc34fe74a67b3.tar.gz rust-5e9b3720e5c49656b78a047922bbc34fe74a67b3.zip | |
Rollup merge of #70733 - yoshuawuyts:arc-increment-refcount, r=Mark-Simulacrum
Add Arc::{incr,decr}_strong_count
This adds two `unsafe` methods to `Arc`: `incr_strong_count` and `decr_strong_count`. A suggestion to add methods to change the strong count in `Arc` came up in during review in https://github.com/rust-lang/rust/pull/68700#discussion_r396169064, and from asking a few people this seemed like generally useful to have.
References:
- [Motivation from #68700](https://github.com/rust-lang/rust/pull/68700#discussion_r396169064)
- [Real world example in an executor](https://docs.rs/extreme/666.666.666666/src/extreme/lib.rs.html#13)
Diffstat (limited to 'src/liballoc/sync.rs')
| -rw-r--r-- | src/liballoc/sync.rs | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index a81e0cf7e1d..19d289c87fd 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -776,6 +776,79 @@ impl<T: ?Sized> Arc<T> { this.inner().strong.load(SeqCst) } + /// Increments the strong reference count on the `Arc<T>` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Arc::into_raw`, and the + /// associated `Arc` instance must be valid (i.e. the strong count must be at + /// least 1) for the duration of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(arc_mutate_strong_count)] + /// + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// unsafe { + /// let ptr = Arc::into_raw(five); + /// Arc::incr_strong_count(ptr); + /// + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` between threads. + /// let five = Arc::from_raw(ptr); + /// assert_eq!(2, Arc::strong_count(&five)); + /// } + /// ``` + #[inline] + #[unstable(feature = "arc_mutate_strong_count", issue = "71983")] + pub unsafe fn incr_strong_count(ptr: *const T) { + // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop + let arc = mem::ManuallyDrop::new(Arc::<T>::from_raw(ptr)); + // Now increase refcount, but don't drop new refcount either + let _arc_clone: mem::ManuallyDrop<_> = arc.clone(); + } + + /// Decrements the strong reference count on the `Arc<T>` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Arc::into_raw`, and the + /// associated `Arc` 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 + /// `Arc` and backing storage, but **should not** be called after the final `Arc` has been + /// released. + /// + /// # Examples + /// + /// ``` + /// #![feature(arc_mutate_strong_count)] + /// + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// unsafe { + /// let ptr = Arc::into_raw(five); + /// Arc::decr_strong_count(ptr); + /// + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` between threads. + /// let five = Arc::from_raw(ptr); + /// assert_eq!(0, Arc::strong_count(&five)); + /// } + /// ``` + #[inline] + #[unstable(feature = "arc_mutate_strong_count", issue = "71983")] + pub unsafe fn decr_strong_count(ptr: *const T) { + mem::drop(Arc::from_raw(ptr)); + } + #[inline] fn inner(&self) -> &ArcInner<T> { // This unsafety is ok because while this arc is alive we're guaranteed |
