From 0602fb0c6e445f75c598f79ee2f77fe8e2019dd0 Mon Sep 17 00:00:00 2001 From: Richard Dodd Date: Mon, 6 Dec 2021 11:25:42 +0000 Subject: impl `Arc::unwrap_or_clone` The function gets the inner value, cloning only if necessary. --- library/alloc/src/sync.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'library/alloc/src') 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 Arc { // 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`, 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 Arc { -- cgit 1.4.1-3-g733a5