Skip to content

Commit

Permalink
Add ptr_eq method for Gc and DerefGc
Browse files Browse the repository at this point in the history
For Gc this is more efficent than doing the comparison directly
on GcGuards, as you avoid taking the internal lockout.
  • Loading branch information
Others committed Nov 2, 2021
1 parent 9bd5729 commit 2befab1
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 13 deletions.
12 changes: 1 addition & 11 deletions src/concurrency/chunked_ll.rs
@@ -1,4 +1,3 @@
use std::mem::{self, MaybeUninit};
use std::ptr;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
use std::sync::Arc;
Expand Down Expand Up @@ -236,14 +235,5 @@ impl<T> ChunkedLinkedList<T> {
}

fn initialize_values<T>() -> [ArcSwapOption<T>; CHUNK_SIZE] {
unsafe {
let mut data: [MaybeUninit<ArcSwapOption<T>>; CHUNK_SIZE] =
MaybeUninit::uninit().assume_init();

for elem in &mut data[..] {
ptr::write(elem.as_mut_ptr(), ArcSwapOption::new(None));
}

mem::transmute(data)
}
[(); CHUNK_SIZE].map(|_| ArcSwapOption::new(None))
}
32 changes: 31 additions & 1 deletion src/smart_ptr/deref_gc.rs
Expand Up @@ -7,10 +7,10 @@ use crate::{Finalize, Scan, Scanner, ToScan};

use std::any::{Any, TypeId};
use std::cmp::Ordering;
use std::fmt;
use std::fmt::{Debug, Display, Formatter};
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::{fmt, ptr};

/// A `Gc`, but with the ability to `Deref` to its contents!
///
Expand Down Expand Up @@ -93,6 +93,14 @@ impl<T: Scan + GcDeref + ?Sized> DerefGc<T> {
direct_ptr: ptr,
}
}

/// `ptr_eq` lets you compare two `DerefGc`s for pointer equality.
///
/// This has the same semantics as `ptr::eq` or `Arc::ptr_eq`.
#[must_use]
pub fn ptr_eq(&self, o: &Self) -> bool {
ptr::eq(self.direct_ptr, o.direct_ptr)
}
}

impl<T: Scan + GcDeref + ?Sized> DerefGc<T> {
Expand Down Expand Up @@ -281,3 +289,25 @@ where
(self.deref()).ge(other.deref())
}
}

#[cfg(test)]
mod test {
use crate::DerefGc;

#[test]
#[allow(clippy::eq_op)]
fn test_eq() {
let a = DerefGc::new(1);
let b = DerefGc::new(1);
assert_eq!(a, a);
assert_eq!(b, b);
assert_eq!(a, b);
assert_eq!(b, a);

assert!(a.ptr_eq(&a));
assert!(b.ptr_eq(&b));
assert!(!a.ptr_eq(&b));
assert!(!b.ptr_eq(&a));
assert!(a.ptr_eq(&a.clone()));
}
}
27 changes: 26 additions & 1 deletion src/smart_ptr/gc.rs
Expand Up @@ -5,10 +5,10 @@ use std::cmp::Ordering;
use std::fmt::{self, Debug, Display, Formatter};
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::sync;
use std::sync::atomic;
#[cfg(feature = "nightly-features")]
use std::{marker::Unsize, ops::CoerceUnsized};
use std::{ptr, sync};

use stable_deref_trait::StableDeref;

Expand Down Expand Up @@ -218,6 +218,14 @@ impl<T: Scan + ?Sized> Gc<T> {
}
}

/// `ptr_eq` lets you compare two `Gc`s for pointer equality.
///
/// This has the same semantics as `ptr::eq` or `Arc::ptr_eq`.
#[must_use]
pub fn ptr_eq(&self, o: &Self) -> bool {
ptr::eq(self.direct_ptr, o.direct_ptr)
}

pub(crate) fn assert_live(&self) {
let ordering = atomic::Ordering::Relaxed;
let is_deallocated = self.backing_handle.data().deallocated.load(ordering);
Expand Down Expand Up @@ -623,4 +631,21 @@ mod test {
let _: Gc<Mutex<dyn NoSize>>;
let _: Gc<RwLock<dyn NoSize>>;
}

#[test]
#[allow(clippy::eq_op)]
fn test_eq() {
let a = Gc::new(1);
let b = Gc::new(1);
assert_eq!(a, a);
assert_eq!(b, b);
assert_eq!(a, b);
assert_eq!(b, a);

assert!(a.ptr_eq(&a));
assert!(b.ptr_eq(&b));
assert!(!a.ptr_eq(&b));
assert!(!b.ptr_eq(&a));
assert!(a.ptr_eq(&a.clone()));
}
}

0 comments on commit 2befab1

Please sign in to comment.