From a7fe969d6eece72464c1236f6d65e2496b27bd52 Mon Sep 17 00:00:00 2001 From: Patrick Norton Date: Sun, 23 May 2021 14:20:27 -0400 Subject: [PATCH 1/3] Added try_into_owned methods --- crossbeam-epoch/src/atomic.rs | 76 +++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/crossbeam-epoch/src/atomic.rs b/crossbeam-epoch/src/atomic.rs index 75a4714ef..501215387 100644 --- a/crossbeam-epoch/src/atomic.rs +++ b/crossbeam-epoch/src/atomic.rs @@ -809,6 +809,52 @@ impl Atomic { Owned::from_usize(self.data.into_inner()) } } + + /// Takes ownership of the pointee if it is non-null. + /// + /// This consumes the atomic and converts it into [`Owned`]. As [`Atomic`] doesn't have a + /// destructor and doesn't drop the pointee while [`Owned`] does, this is suitable for + /// destructors of data structures. + /// + /// # Safety + /// + /// This method may be called only if the pointer is valid and nobody else is holding a + /// reference to the same object, or the pointer is null.. + /// + /// # Examples + /// + /// ```rust + /// # use std::mem; + /// # use crossbeam_epoch::Atomic; + /// struct DataStructure { + /// ptr: Atomic, + /// } + /// + /// impl Drop for DataStructure { + /// fn drop(&mut self) { + /// // By now the DataStructure lives only in our thread and we are sure we don't hold + /// // any Shared or & to it ourselves, but it may be null, so we have to be careful. + /// let old = mem::replace(&mut self.ptr, Atomic::null()); + /// unsafe { + /// if let Option::Some(x) = old.try_into_owned() { + /// drop(x) + /// } + /// } + /// } + /// } + /// ``` + pub unsafe fn try_into_owned(self) -> Option> { + // FIXME: See self.into_owned() + #[cfg(crossbeam_loom)] + let data = self.data.unsync_load(); + #[cfg(not(crossbeam_loom))] + let data = self.data.into_inner(); + if decompose_tag::(data).0 == 0 { + Option::None + } else { + Option::Some(Owned::from_usize(data)) + } + } } impl fmt::Debug for Atomic { @@ -1419,6 +1465,36 @@ impl<'g, T: ?Sized + Pointable> Shared<'g, T> { Owned::from_usize(self.data) } + /// Takes ownership of the pointee if it is not null. + /// + /// # Safety + /// + /// This method may be called only if the pointer is valid and nobody else is holding a + /// reference to the same object, or if the pointer is null. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(1234); + /// unsafe { + /// let guard = &epoch::unprotected(); + /// let p = a.load(SeqCst, guard); + /// if let Option::Some(x) = p.try_into_owned() { + /// drop(x); + /// } + /// } + /// ``` + pub unsafe fn try_into_owned(self) -> Option> { + if self.is_null() { + Option::None + } else { + Option::Some(Owned::from_usize(self.data)) + } + } + /// Returns the tag stored within the pointer. /// /// # Examples From 3419a6f320c909f11ac43a729cbe6333fd93f88b Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 28 May 2022 18:20:12 +0900 Subject: [PATCH 2/3] Fix typo in crossbeam-epoch/src/atomic.rs --- crossbeam-epoch/src/atomic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crossbeam-epoch/src/atomic.rs b/crossbeam-epoch/src/atomic.rs index 501215387..a608e8ef2 100644 --- a/crossbeam-epoch/src/atomic.rs +++ b/crossbeam-epoch/src/atomic.rs @@ -819,7 +819,7 @@ impl Atomic { /// # Safety /// /// This method may be called only if the pointer is valid and nobody else is holding a - /// reference to the same object, or the pointer is null.. + /// reference to the same object, or the pointer is null. /// /// # Examples /// From b27e55fdc6cf836c12f7a36a816620cc1afca93d Mon Sep 17 00:00:00 2001 From: PatrickNorton <36009535+PatrickNorton@users.noreply.github.com> Date: Tue, 19 Jul 2022 19:13:17 -0600 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Taiki Endo --- crossbeam-epoch/src/atomic.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crossbeam-epoch/src/atomic.rs b/crossbeam-epoch/src/atomic.rs index a608e8ef2..d7fb13a00 100644 --- a/crossbeam-epoch/src/atomic.rs +++ b/crossbeam-epoch/src/atomic.rs @@ -836,7 +836,7 @@ impl Atomic { /// // any Shared or & to it ourselves, but it may be null, so we have to be careful. /// let old = mem::replace(&mut self.ptr, Atomic::null()); /// unsafe { - /// if let Option::Some(x) = old.try_into_owned() { + /// if let Some(x) = old.try_into_owned() { /// drop(x) /// } /// } @@ -850,9 +850,9 @@ impl Atomic { #[cfg(not(crossbeam_loom))] let data = self.data.into_inner(); if decompose_tag::(data).0 == 0 { - Option::None + None } else { - Option::Some(Owned::from_usize(data)) + Some(Owned::from_usize(data)) } } } @@ -1482,16 +1482,16 @@ impl<'g, T: ?Sized + Pointable> Shared<'g, T> { /// unsafe { /// let guard = &epoch::unprotected(); /// let p = a.load(SeqCst, guard); - /// if let Option::Some(x) = p.try_into_owned() { + /// if let Some(x) = p.try_into_owned() { /// drop(x); /// } /// } /// ``` pub unsafe fn try_into_owned(self) -> Option> { if self.is_null() { - Option::None + None } else { - Option::Some(Owned::from_usize(self.data)) + Some(Owned::from_usize(self.data)) } }