diff options
| author | Richard Dodd <richard.o.dodd@gmail.com> | 2021-12-06 11:25:42 +0000 |
|---|---|---|
| committer | Richard Dodd <richard.o.dodd@gmail.com> | 2022-02-03 09:16:04 +0000 |
| commit | 0602fb0c6e445f75c598f79ee2f77fe8e2019dd0 (patch) | |
| tree | 92918904c76d7105012e14b6d18db5cbc08760df /library/alloc/src | |
| parent | 1be5c8f90912c446ecbdc405cbc4a89f9acd20fd (diff) | |
| download | rust-0602fb0c6e445f75c598f79ee2f77fe8e2019dd0.tar.gz rust-0602fb0c6e445f75c598f79ee2f77fe8e2019dd0.zip | |
impl `Arc::unwrap_or_clone`
The function gets the inner value, cloning only if necessary.
Diffstat (limited to 'library/alloc/src')
| -rw-r--r-- | library/alloc/src/sync.rs | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 64f21d087da..3d132484b2f 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1477,6 +1477,41 @@ impl<T: Clone> Arc<T> { // either unique to begin with, or became one upon cloning the contents. unsafe { Self::get_mut_unchecked(this) } } + + /// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the + /// clone. + /// + /// Assuming `arc_t` is of type `Arc<T>`, this function is functionally equivalent to + /// `(*arc_t).clone()`, but will avoid cloning the inner value where possible. + /// + /// # Examples + /// + /// ``` + /// #![feature(arc_unwrap_or_clone)] + /// # use std::{ptr, sync::Arc}; + /// let inner = String::from("test"); + /// let ptr = inner.as_ptr(); + /// + /// let arc = Arc::new(inner); + /// let inner = Arc::unwrap_or_clone(arc); + /// // The inner value was not cloned + /// assert!(ptr::eq(ptr, inner.as_ptr())); + /// + /// let arc = Arc::new(inner); + /// let arc2 = arc.clone(); + /// let inner = Arc::unwrap_or_clone(arc); + /// // Because there were 2 references, we had to clone the inner value. + /// assert!(!ptr::eq(ptr, inner.as_ptr())); + /// // `arc2` is the last reference, so when we unwrap it we get back + /// // the original `String`. + /// let inner = Arc::unwrap_or_clone(arc2); + /// assert!(ptr::eq(ptr, inner.as_ptr())); + /// ``` + #[inline] + #[unstable(feature = "arc_unwrap_or_clone", issue = "none")] + pub fn unwrap_or_clone(this: Self) -> T { + Arc::try_unwrap(this).unwrap_or_else(|arc| (*arc).clone()) + } } impl<T: ?Sized> Arc<T> { |
