diff --git a/crossbeam-skiplist/Cargo.toml b/crossbeam-skiplist/Cargo.toml index 75a0df46b..4d1eaddb5 100644 --- a/crossbeam-skiplist/Cargo.toml +++ b/crossbeam-skiplist/Cargo.toml @@ -4,7 +4,7 @@ name = "crossbeam-skiplist" # - Update CHANGELOG.md # - Update README.md (when increasing major or minor version) # - Run './tools/publish.sh crossbeam-skiplist ' -version = "0.1.3" +version = "0.1.4" edition = "2021" rust-version = "1.61" license = "MIT OR Apache-2.0" @@ -28,6 +28,7 @@ std = ["alloc", "crossbeam-epoch/std", "crossbeam-utils/std"] alloc = ["crossbeam-epoch/alloc"] [dependencies] +equivalent = "1" crossbeam-epoch = { version = "0.9.17", path = "../crossbeam-epoch", default-features = false } crossbeam-utils = { version = "0.8.18", path = "../crossbeam-utils", default-features = false } diff --git a/crossbeam-skiplist/src/base.rs b/crossbeam-skiplist/src/base.rs index f3c90b1f9..314f227ae 100644 --- a/crossbeam-skiplist/src/base.rs +++ b/crossbeam-skiplist/src/base.rs @@ -9,6 +9,7 @@ use core::mem; use core::ops::{Bound, Deref, Index, RangeBounds}; use core::ptr; use core::sync::atomic::{fence, AtomicUsize, Ordering}; +use equivalent::Comparable; use crossbeam_epoch::{self as epoch, Atomic, Collector, Guard, Shared}; use crossbeam_utils::CachePadded; @@ -398,7 +399,7 @@ where /// Returns the entry with the largest key. pub fn back<'a: 'g, 'g>(&'a self, guard: &'g Guard) -> Option> { self.check_guard(guard); - let n = self.search_bound(Bound::Unbounded, true, guard)?; + let n = self.search_bound::(Bound::Unbounded, true, guard)?; Some(Entry { parent: self, node: n, @@ -409,8 +410,7 @@ where /// Returns `true` if the map contains a value for the specified key. pub fn contains_key(&self, key: &Q, guard: &Guard) -> bool where - K: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { self.get(key, guard).is_some() } @@ -418,12 +418,11 @@ where /// Returns an entry with the specified `key`. pub fn get<'a: 'g, 'g, Q>(&'a self, key: &Q, guard: &'g Guard) -> Option> where - K: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { self.check_guard(guard); let n = self.search_bound(Bound::Included(key), false, guard)?; - if n.key.borrow() != key { + if key.compare(&n.key).is_ne() { return None; } Some(Entry { @@ -442,8 +441,7 @@ where guard: &'g Guard, ) -> Option> where - K: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { self.check_guard(guard); let n = self.search_bound(bound, false, guard)?; @@ -463,8 +461,7 @@ where guard: &'g Guard, ) -> Option> where - K: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { self.check_guard(guard); let n = self.search_bound(bound, true, guard)?; @@ -524,7 +521,7 @@ where where K: Borrow, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { self.check_guard(guard); Range { @@ -541,9 +538,8 @@ where #[allow(clippy::needless_lifetimes)] pub fn ref_range<'a, Q, R>(&'a self, range: R) -> RefRange<'a, Q, R, K, V> where - K: Borrow, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { RefRange { parent: self, @@ -685,8 +681,7 @@ where guard: &'a Guard, ) -> Option<&'a Node> where - K: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { unsafe { 'search: loop { @@ -767,8 +762,7 @@ where /// Searches for a key in the skip list and returns a list of all adjacent nodes. fn search_position<'a, Q>(&'a self, key: &Q, guard: &'a Guard) -> Position<'a, K, V> where - K: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { unsafe { 'search: loop { @@ -825,7 +819,7 @@ where // If `curr` contains a key that is greater than or equal to `key`, we're // done with this level. - match c.key.borrow().cmp(key) { + match key.compare(&c.key).reverse() { cmp::Ordering::Greater => break, cmp::Ordering::Equal => { result.found = Some(c); @@ -1101,8 +1095,7 @@ where /// Removes an entry with the specified `key` from the map and returns it. pub fn remove(&self, key: &Q, guard: &Guard) -> Option> where - K: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { self.check_guard(guard); @@ -1208,7 +1201,7 @@ where // By unlinking nodes in batches we make sure that the final search doesn't // unlink all nodes at once, which could keep the current thread pinned for a // long time. - let mut entry = self.lower_bound(Bound::Unbounded, guard); + let mut entry = self.lower_bound::(Bound::Unbounded, guard); for _ in 0..BATCH_SIZE { // Stop if we have reached the end of the list. @@ -1663,7 +1656,9 @@ where Some(n) => self .parent .search_bound(Bound::Excluded(&n.key), true, self.guard), - None => self.parent.search_bound(Bound::Unbounded, true, self.guard), + None => self + .parent + .search_bound::(Bound::Unbounded, true, self.guard), }; if let (Some(h), Some(t)) = (self.head, self.tail) { if h.key >= t.key { @@ -1793,9 +1788,9 @@ impl<'a, K: 'a, V: 'a> RefIter<'a, K, V> { /// An iterator over a subset of entries of a `SkipList`. pub struct Range<'a: 'g, 'g, Q, R, K, V> where - K: Ord + Borrow, + K: Ord, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { parent: &'a SkipList, head: Option<&'g Node>, @@ -1807,9 +1802,9 @@ where impl<'a: 'g, 'g, Q, R, K: 'a, V: 'a> Iterator for Range<'a, 'g, Q, R, K, V> where - K: Ord + Borrow, + K: Ord, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { type Item = Entry<'a, 'g, K, V>; @@ -1823,14 +1818,22 @@ where .search_bound(self.range.start_bound(), false, self.guard), }; if let Some(h) = self.head { - let bound = match self.tail { - Some(t) => Bound::Excluded(t.key.borrow()), - None => self.range.end_bound(), + match self.tail { + Some(t) => { + let bound = Bound::Excluded(&t.key); + if !below_upper_bound(&bound, &h.key) { + self.head = None; + self.tail = None; + } + } + None => { + let bound = self.range.end_bound(); + if !below_upper_bound(&bound, &h.key) { + self.head = None; + self.tail = None; + } + } }; - if !below_upper_bound(&bound, h.key.borrow()) { - self.head = None; - self.tail = None; - } } self.head.map(|n| Entry { parent: self.parent, @@ -1842,9 +1845,9 @@ where impl<'a: 'g, 'g, Q, R, K: 'a, V: 'a> DoubleEndedIterator for Range<'a, 'g, Q, R, K, V> where - K: Ord + Borrow, + K: Ord, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { fn next_back(&mut self) -> Option> { self.tail = match self.tail { @@ -1856,14 +1859,22 @@ where .search_bound(self.range.end_bound(), true, self.guard), }; if let Some(t) = self.tail { - let bound = match self.head { - Some(h) => Bound::Excluded(h.key.borrow()), - None => self.range.start_bound(), + match self.head { + Some(h) => { + let bound = Bound::Excluded(h.key.borrow()); + if !above_lower_bound(&bound, &t.key) { + self.head = None; + self.tail = None; + } + } + None => { + let bound = self.range.start_bound(); + if !above_lower_bound(&bound, &t.key) { + self.head = None; + self.tail = None; + } + } }; - if !above_lower_bound(&bound, t.key.borrow()) { - self.head = None; - self.tail = None; - } } self.tail.map(|n| Entry { parent: self.parent, @@ -1875,10 +1886,10 @@ where impl fmt::Debug for Range<'_, '_, Q, R, K, V> where - K: Ord + Borrow + fmt::Debug, + K: Ord + fmt::Debug, V: fmt::Debug, R: RangeBounds + fmt::Debug, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Range") @@ -1892,9 +1903,8 @@ where /// An iterator over reference-counted subset of entries of a `SkipList`. pub struct RefRange<'a, Q, R, K, V> where - K: Ord + Borrow, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { parent: &'a SkipList, pub(crate) head: Option>, @@ -1905,26 +1915,24 @@ where unsafe impl Send for RefRange<'_, Q, R, K, V> where - K: Ord + Borrow, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { } unsafe impl Sync for RefRange<'_, Q, R, K, V> where - K: Ord + Borrow, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { } impl fmt::Debug for RefRange<'_, Q, R, K, V> where - K: Ord + Borrow + fmt::Debug, + K: fmt::Debug, V: fmt::Debug, R: RangeBounds + fmt::Debug, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RefRange") @@ -1937,9 +1945,26 @@ where impl<'a, Q, R, K: 'a, V: 'a> RefRange<'a, Q, R, K, V> where - K: Ord + Borrow, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, +{ + /// Decrements a reference count owned by this iterator. + pub fn drop_impl(&mut self, guard: &Guard) { + self.parent.check_guard(guard); + if let Some(e) = self.head.take() { + unsafe { e.node.decrement(guard) }; + } + if let Some(e) = self.tail.take() { + unsafe { e.node.decrement(guard) }; + } + } +} + +impl<'a, Q, R, K: 'a, V: 'a> RefRange<'a, Q, R, K, V> +where + K: Ord, + R: RangeBounds, + Q: ?Sized + Comparable, { /// Advances the iterator and returns the next value. pub fn next(&mut self, guard: &Guard) -> Option> { @@ -1950,18 +1975,31 @@ where }; if let Some(ref h) = next_head { - let bound = match self.tail { - Some(ref t) => Bound::Excluded(t.key().borrow()), - None => self.range.end_bound(), - }; - if below_upper_bound(&bound, h.key().borrow()) { - self.head.clone_from(&next_head); - next_head - } else { - unsafe { - h.node.decrement(guard); + match self.tail { + Some(ref t) => { + let bound = Bound::Excluded(t.key()); + if below_upper_bound(&bound, h.key()) { + self.head.clone_from(&next_head); + next_head + } else { + unsafe { + h.node.decrement(guard); + } + None + } + } + None => { + let bound = self.range.end_bound(); + if below_upper_bound(&bound, h.key()) { + self.head.clone_from(&next_head); + next_head + } else { + unsafe { + h.node.decrement(guard); + } + None + } } - None } } else { None @@ -1977,34 +2015,36 @@ where }; if let Some(ref t) = next_tail { - let bound = match self.head { - Some(ref h) => Bound::Excluded(h.key().borrow()), - None => self.range.start_bound(), - }; - if above_lower_bound(&bound, t.key().borrow()) { - self.tail.clone_from(&next_tail); - next_tail - } else { - unsafe { - t.node.decrement(guard); + match self.head { + Some(ref h) => { + let bound = Bound::Excluded(h.key()); + if above_lower_bound(&bound, t.key()) { + self.tail.clone_from(&next_tail); + next_tail + } else { + unsafe { + t.node.decrement(guard); + } + None + } + } + None => { + let bound = self.range.start_bound(); + if above_lower_bound(&bound, t.key()) { + self.tail.clone_from(&next_tail); + next_tail + } else { + unsafe { + t.node.decrement(guard); + } + None + } } - None } } else { None } } - - /// Decrements a reference count owned by this iterator. - pub fn drop_impl(&mut self, guard: &Guard) { - self.parent.check_guard(guard); - if let Some(e) = self.head.take() { - unsafe { e.node.decrement(guard) }; - } - if let Some(e) = self.tail.take() { - unsafe { e.node.decrement(guard) }; - } - } } /// An owning iterator over the entries of a `SkipList`. @@ -2089,19 +2129,19 @@ where } /// Helper function to check if a value is above a lower bound -fn above_lower_bound(bound: &Bound<&T>, other: &T) -> bool { +fn above_lower_bound>(bound: &Bound<&T>, other: &V) -> bool { match *bound { Bound::Unbounded => true, - Bound::Included(key) => other >= key, - Bound::Excluded(key) => other > key, + Bound::Included(key) => key.compare(other).is_le(), + Bound::Excluded(key) => key.compare(other).is_lt(), } } /// Helper function to check if a value is below an upper bound -fn below_upper_bound(bound: &Bound<&T>, other: &T) -> bool { +fn below_upper_bound>(bound: &Bound<&T>, other: &V) -> bool { match *bound { Bound::Unbounded => true, - Bound::Included(key) => other <= key, - Bound::Excluded(key) => other < key, + Bound::Included(key) => key.compare(other).is_ge(), + Bound::Excluded(key) => key.compare(other).is_gt(), } } diff --git a/crossbeam-skiplist/src/map.rs b/crossbeam-skiplist/src/map.rs index e131e79a9..353a1d8ef 100644 --- a/crossbeam-skiplist/src/map.rs +++ b/crossbeam-skiplist/src/map.rs @@ -1,6 +1,5 @@ //! An ordered map based on a lock-free skip list. See [`SkipMap`]. -use std::borrow::Borrow; use std::fmt; use std::mem::ManuallyDrop; use std::ops::{Bound, RangeBounds}; @@ -8,6 +7,7 @@ use std::ptr; use crate::base::{self, try_pin_loop}; use crossbeam_epoch as epoch; +use equivalent::Comparable; /// An ordered map based on a lock-free skip list. /// @@ -133,8 +133,7 @@ where /// ``` pub fn contains_key(&self, key: &Q) -> bool where - K: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { let guard = &epoch::pin(); self.inner.contains_key(key, guard) @@ -157,8 +156,7 @@ where /// ``` pub fn get(&self, key: &Q) -> Option> where - K: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { let guard = &epoch::pin(); try_pin_loop(|| self.inner.get(key, guard)).map(Entry::new) @@ -192,8 +190,7 @@ where /// ``` pub fn lower_bound<'a, Q>(&'a self, bound: Bound<&Q>) -> Option> where - K: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { let guard = &epoch::pin(); try_pin_loop(|| self.inner.lower_bound(bound, guard)).map(Entry::new) @@ -224,8 +221,7 @@ where /// ``` pub fn upper_bound<'a, Q>(&'a self, bound: Bound<&Q>) -> Option> where - K: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { let guard = &epoch::pin(); try_pin_loop(|| self.inner.upper_bound(bound, guard)).map(Entry::new) @@ -337,9 +333,8 @@ where /// ``` pub fn range(&self, range: R) -> Range<'_, Q, R, K, V> where - K: Borrow, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { Range { inner: self.inner.ref_range(range), @@ -424,8 +419,7 @@ where /// ``` pub fn remove(&self, key: &Q) -> Option> where - K: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { let guard = &epoch::pin(); self.inner.remove(key, guard).map(Entry::new) @@ -721,18 +715,17 @@ impl Drop for Iter<'_, K, V> { /// An iterator over a subset of entries of a `SkipMap`. pub struct Range<'a, Q, R, K, V> where - K: Ord + Borrow, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { pub(crate) inner: base::RefRange<'a, Q, R, K, V>, } impl<'a, Q, R, K, V> Iterator for Range<'a, Q, R, K, V> where - K: Ord + Borrow, + K: Ord, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { type Item = Entry<'a, K, V>; @@ -744,9 +737,9 @@ where impl<'a, Q, R, K, V> DoubleEndedIterator for Range<'a, Q, R, K, V> where - K: Ord + Borrow, + K: Ord, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { fn next_back(&mut self) -> Option> { let guard = &epoch::pin(); @@ -756,10 +749,10 @@ where impl fmt::Debug for Range<'_, Q, R, K, V> where - K: Ord + Borrow + fmt::Debug, + K: fmt::Debug, V: fmt::Debug, R: RangeBounds + fmt::Debug, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Range") @@ -772,9 +765,8 @@ where impl Drop for Range<'_, Q, R, K, V> where - K: Ord + Borrow, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { fn drop(&mut self) { let guard = &epoch::pin(); diff --git a/crossbeam-skiplist/src/set.rs b/crossbeam-skiplist/src/set.rs index b185ff8ba..b61b496e0 100644 --- a/crossbeam-skiplist/src/set.rs +++ b/crossbeam-skiplist/src/set.rs @@ -1,10 +1,11 @@ //! A set based on a lock-free skip list. See [`SkipSet`]. -use std::borrow::Borrow; use std::fmt; use std::ops::Deref; use std::ops::{Bound, RangeBounds}; +use equivalent::Comparable; + use crate::map; /// A set based on a lock-free skip list. @@ -122,8 +123,7 @@ where /// ``` pub fn contains(&self, key: &Q) -> bool where - T: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { self.inner.contains_key(key) } @@ -141,8 +141,7 @@ where /// ``` pub fn get(&self, key: &Q) -> Option> where - T: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { self.inner.get(key).map(Entry::new) } @@ -173,8 +172,7 @@ where /// ``` pub fn lower_bound<'a, Q>(&'a self, bound: Bound<&Q>) -> Option> where - T: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { self.inner.lower_bound(bound).map(Entry::new) } @@ -202,8 +200,7 @@ where /// ``` pub fn upper_bound<'a, Q>(&'a self, bound: Bound<&Q>) -> Option> where - T: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { self.inner.upper_bound(bound).map(Entry::new) } @@ -266,9 +263,8 @@ where /// ``` pub fn range(&self, range: R) -> Range<'_, Q, R, T> where - T: Borrow, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { Range { inner: self.inner.range(range), @@ -315,8 +311,7 @@ where /// ``` pub fn remove(&self, key: &Q) -> Option> where - T: Borrow, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { self.inner.remove(key).map(Entry::new) } @@ -582,18 +577,17 @@ impl fmt::Debug for Iter<'_, T> { /// An iterator over a subset of entries of a `SkipSet`. pub struct Range<'a, Q, R, T> where - T: Ord + Borrow, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { inner: map::Range<'a, Q, R, T, ()>, } impl<'a, Q, R, T> Iterator for Range<'a, Q, R, T> where - T: Ord + Borrow, + T: Ord, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { type Item = Entry<'a, T>; @@ -604,9 +598,9 @@ where impl<'a, Q, R, T> DoubleEndedIterator for Range<'a, Q, R, T> where - T: Ord + Borrow, + T: Ord, R: RangeBounds, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { fn next_back(&mut self) -> Option> { self.inner.next_back().map(Entry::new) @@ -615,9 +609,9 @@ where impl fmt::Debug for Range<'_, Q, R, T> where - T: Ord + Borrow + fmt::Debug, + T: fmt::Debug, R: RangeBounds + fmt::Debug, - Q: Ord + ?Sized, + Q: ?Sized + Comparable, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Range") diff --git a/crossbeam-skiplist/tests/base.rs b/crossbeam-skiplist/tests/base.rs index 83d2f221e..7af6fa1c5 100644 --- a/crossbeam-skiplist/tests/base.rs +++ b/crossbeam-skiplist/tests/base.rs @@ -281,7 +281,12 @@ fn lower_bound() { s.insert(40, 4, guard).release(guard); s.insert(20, 2, guard).release(guard); - assert_eq!(*s.lower_bound(Bound::Unbounded, guard).unwrap().value(), 1); + assert_eq!( + *s.lower_bound::(Bound::Unbounded, guard) + .unwrap() + .value(), + 1 + ); assert_eq!( *s.lower_bound(Bound::Included(&10), guard).unwrap().value(), @@ -361,7 +366,12 @@ fn upper_bound() { s.insert(40, 4, guard).release(guard); s.insert(20, 2, guard).release(guard); - assert_eq!(*s.upper_bound(Bound::Unbounded, guard).unwrap().value(), 5); + assert_eq!( + *s.upper_bound::(Bound::Unbounded, guard) + .unwrap() + .value(), + 5 + ); assert_eq!( *s.upper_bound(Bound::Included(&10), guard).unwrap().value(), @@ -900,3 +910,73 @@ fn drops() { assert_eq!(KEYS.load(Ordering::SeqCst), 8); assert_eq!(VALUES.load(Ordering::SeqCst), 7); } + +#[test] +fn comparable_get() { + use equivalent::{Comparable, Equivalent}; + + #[derive(PartialEq, Eq, PartialOrd, Ord)] + struct Foo { + a: u64, + b: u32, + } + + #[derive(PartialEq, Eq)] + struct FooRef<'a> { + data: &'a [u8], + } + + impl PartialOrd for FooRef<'_> { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } + } + + impl Ord for FooRef<'_> { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + let a = u64::from_be_bytes(self.data[..8].try_into().unwrap()); + let b = u32::from_be_bytes(self.data[8..].try_into().unwrap()); + let other_a = u64::from_be_bytes(other.data[..8].try_into().unwrap()); + let other_b = u32::from_be_bytes(other.data[8..].try_into().unwrap()); + Foo { a, b }.cmp(&Foo { + a: other_a, + b: other_b, + }) + } + } + + impl Equivalent for FooRef<'_> { + fn equivalent(&self, key: &Foo) -> bool { + let a = u64::from_be_bytes(self.data[..8].try_into().unwrap()); + let b = u32::from_be_bytes(self.data[8..].try_into().unwrap()); + a == key.a && b == key.b + } + } + + impl Comparable for FooRef<'_> { + fn compare(&self, key: &Foo) -> std::cmp::Ordering { + let a = u64::from_be_bytes(self.data[..8].try_into().unwrap()); + let b = u32::from_be_bytes(self.data[8..].try_into().unwrap()); + Foo { a, b }.cmp(key) + } + } + + let s = SkipList::new(epoch::default_collector().clone()); + let foo = Foo { a: 1, b: 2 }; + + let g = &epoch::pin(); + s.insert(foo, 12, g); + + let buf = 1u64 + .to_be_bytes() + .iter() + .chain(2u32.to_be_bytes().iter()) + .copied() + .collect::>(); + let foo_ref = FooRef { data: &buf }; + + let ent = s.get(&foo_ref, g).unwrap(); + assert_eq!(ent.key().a, 1); + assert_eq!(ent.key().b, 2); + assert_eq!(*ent.value(), 12); +} diff --git a/crossbeam-skiplist/tests/map.rs b/crossbeam-skiplist/tests/map.rs index 3b734f110..903ba3cba 100644 --- a/crossbeam-skiplist/tests/map.rs +++ b/crossbeam-skiplist/tests/map.rs @@ -443,7 +443,7 @@ fn lower_bound() { s.insert(40, 4); s.insert(20, 2); - assert_eq!(*s.lower_bound(Bound::Unbounded).unwrap().value(), 1); + assert_eq!(*s.lower_bound::(Bound::Unbounded).unwrap().value(), 1); assert_eq!(*s.lower_bound(Bound::Included(&10)).unwrap().value(), 1); assert_eq!(*s.lower_bound(Bound::Included(&20)).unwrap().value(), 2); @@ -477,7 +477,7 @@ fn upper_bound() { s.insert(40, 4); s.insert(20, 2); - assert_eq!(*s.upper_bound(Bound::Unbounded).unwrap().value(), 5); + assert_eq!(*s.upper_bound::(Bound::Unbounded).unwrap().value(), 5); assert_eq!(*s.upper_bound(Bound::Included(&10)).unwrap().value(), 1); assert_eq!(*s.upper_bound(Bound::Included(&20)).unwrap().value(), 2); @@ -670,210 +670,212 @@ fn iter_range() { vec![90, 80, 70, 60, 50, 40, 30, 20, 10, 0] ); assert_eq!( - s.range(..).map(|x| *x.value()).collect::>(), + s.range::(..) + .map(|x| *x.value()) + .collect::>(), vec![0, 10, 20, 30, 40, 50, 60, 70, 80, 90] ); assert_eq!( - s.range((Included(&0), Unbounded)) + s.range::((Included(&0), Unbounded)) .map(|x| *x.value()) .collect::>(), vec![0, 10, 20, 30, 40, 50, 60, 70, 80, 90] ); assert_eq!( - s.range((Included(&0), Included(&60))) + s.range::((Included(&0), Included(&60))) .rev() .map(|x| *x.value()) .collect::>(), vec![60, 50, 40, 30, 20, 10, 0] ); assert_eq!( - s.range((Excluded(&0), Unbounded)) + s.range::((Excluded(&0), Unbounded)) .map(|x| *x.value()) .collect::>(), vec![10, 20, 30, 40, 50, 60, 70, 80, 90] ); assert_eq!( - s.range((Included(&25), Unbounded)) + s.range::((Included(&25), Unbounded)) .map(|x| *x.value()) .collect::>(), vec![30, 40, 50, 60, 70, 80, 90] ); assert_eq!( - s.range((Excluded(&25), Unbounded)) + s.range::((Excluded(&25), Unbounded)) .map(|x| *x.value()) .collect::>(), vec![30, 40, 50, 60, 70, 80, 90] ); assert_eq!( - s.range((Included(&70), Unbounded)) + s.range::((Included(&70), Unbounded)) .map(|x| *x.value()) .collect::>(), vec![70, 80, 90] ); assert_eq!( - s.range((Excluded(&70), Unbounded)) + s.range::((Excluded(&70), Unbounded)) .map(|x| *x.value()) .collect::>(), vec![80, 90] ); assert_eq!( - s.range((Included(&100), Unbounded)) + s.range::((Included(&100), Unbounded)) .map(|x| *x.value()) .collect::>(), vec![] ); assert_eq!( - s.range((Excluded(&100), Unbounded)) + s.range::((Excluded(&100), Unbounded)) .map(|x| *x.value()) .collect::>(), vec![] ); assert_eq!( - s.range((Unbounded, Included(&90))) + s.range::((Unbounded, Included(&90))) .map(|x| *x.value()) .collect::>(), vec![0, 10, 20, 30, 40, 50, 60, 70, 80, 90] ); assert_eq!( - s.range((Unbounded, Excluded(&90))) + s.range::((Unbounded, Excluded(&90))) .map(|x| *x.value()) .collect::>(), vec![0, 10, 20, 30, 40, 50, 60, 70, 80] ); assert_eq!( - s.range((Unbounded, Included(&25))) + s.range::((Unbounded, Included(&25))) .map(|x| *x.value()) .collect::>(), vec![0, 10, 20] ); assert_eq!( - s.range((Unbounded, Excluded(&25))) + s.range::((Unbounded, Excluded(&25))) .map(|x| *x.value()) .collect::>(), vec![0, 10, 20] ); assert_eq!( - s.range((Unbounded, Included(&70))) + s.range::((Unbounded, Included(&70))) .map(|x| *x.value()) .collect::>(), vec![0, 10, 20, 30, 40, 50, 60, 70] ); assert_eq!( - s.range((Unbounded, Excluded(&70))) + s.range::((Unbounded, Excluded(&70))) .map(|x| *x.value()) .collect::>(), vec![0, 10, 20, 30, 40, 50, 60] ); assert_eq!( - s.range((Unbounded, Included(&-1))) + s.range::((Unbounded, Included(&-1))) .map(|x| *x.value()) .collect::>(), vec![] ); assert_eq!( - s.range((Unbounded, Excluded(&-1))) + s.range::((Unbounded, Excluded(&-1))) .map(|x| *x.value()) .collect::>(), vec![] ); assert_eq!( - s.range((Included(&25), Included(&80))) + s.range::((Included(&25), Included(&80))) .map(|x| *x.value()) .collect::>(), vec![30, 40, 50, 60, 70, 80] ); assert_eq!( - s.range((Included(&25), Excluded(&80))) + s.range::((Included(&25), Excluded(&80))) .map(|x| *x.value()) .collect::>(), vec![30, 40, 50, 60, 70] ); assert_eq!( - s.range((Excluded(&25), Included(&80))) + s.range::((Excluded(&25), Included(&80))) .map(|x| *x.value()) .collect::>(), vec![30, 40, 50, 60, 70, 80] ); assert_eq!( - s.range((Excluded(&25), Excluded(&80))) + s.range::((Excluded(&25), Excluded(&80))) .map(|x| *x.value()) .collect::>(), vec![30, 40, 50, 60, 70] ); assert_eq!( - s.range((Included(&25), Included(&25))) + s.range::((Included(&25), Included(&25))) .map(|x| *x.value()) .collect::>(), vec![] ); assert_eq!( - s.range((Included(&25), Excluded(&25))) + s.range::((Included(&25), Excluded(&25))) .map(|x| *x.value()) .collect::>(), vec![] ); assert_eq!( - s.range((Excluded(&25), Included(&25))) + s.range::((Excluded(&25), Included(&25))) .map(|x| *x.value()) .collect::>(), vec![] ); assert_eq!( - s.range((Excluded(&25), Excluded(&25))) + s.range::((Excluded(&25), Excluded(&25))) .map(|x| *x.value()) .collect::>(), vec![] ); assert_eq!( - s.range((Included(&50), Included(&50))) + s.range::((Included(&50), Included(&50))) .map(|x| *x.value()) .collect::>(), vec![50] ); assert_eq!( - s.range((Included(&50), Excluded(&50))) + s.range::((Included(&50), Excluded(&50))) .map(|x| *x.value()) .collect::>(), vec![] ); assert_eq!( - s.range((Excluded(&50), Included(&50))) + s.range::((Excluded(&50), Included(&50))) .map(|x| *x.value()) .collect::>(), vec![] ); assert_eq!( - s.range((Excluded(&50), Excluded(&50))) + s.range::((Excluded(&50), Excluded(&50))) .map(|x| *x.value()) .collect::>(), vec![] ); assert_eq!( - s.range((Included(&100), Included(&-2))) + s.range::((Included(&100), Included(&-2))) .map(|x| *x.value()) .collect::>(), vec![] ); assert_eq!( - s.range((Included(&100), Excluded(&-2))) + s.range::((Included(&100), Excluded(&-2))) .map(|x| *x.value()) .collect::>(), vec![] ); assert_eq!( - s.range((Excluded(&100), Included(&-2))) + s.range::((Excluded(&100), Included(&-2))) .map(|x| *x.value()) .collect::>(), vec![] ); assert_eq!( - s.range((Excluded(&100), Excluded(&-2))) + s.range::((Excluded(&100), Excluded(&-2))) .map(|x| *x.value()) .collect::>(), vec![] diff --git a/crossbeam-skiplist/tests/set.rs b/crossbeam-skiplist/tests/set.rs index ab769003c..cae3d4aea 100644 --- a/crossbeam-skiplist/tests/set.rs +++ b/crossbeam-skiplist/tests/set.rs @@ -292,7 +292,7 @@ fn lower_bound() { s.insert(40); s.insert(20); - assert_eq!(*s.lower_bound(Bound::Unbounded).unwrap(), 10); + assert_eq!(*s.lower_bound::(Bound::Unbounded).unwrap(), 10); assert_eq!(*s.lower_bound(Bound::Included(&10)).unwrap(), 10); assert_eq!(*s.lower_bound(Bound::Included(&20)).unwrap(), 20); @@ -326,7 +326,7 @@ fn upper_bound() { s.insert(40); s.insert(20); - assert_eq!(*s.upper_bound(Bound::Unbounded).unwrap(), 50); + assert_eq!(*s.upper_bound::(Bound::Unbounded).unwrap(), 50); assert_eq!(*s.upper_bound(Bound::Included(&10)).unwrap(), 10); assert_eq!(*s.upper_bound(Bound::Included(&20)).unwrap(), 20); @@ -458,203 +458,203 @@ fn iter_range() { vec![90, 80, 70, 60, 50, 40, 30, 20, 10, 0] ); assert_eq!( - s.range(..).map(|x| *x).collect::>(), + s.range::(..).map(|x| *x).collect::>(), vec![0, 10, 20, 30, 40, 50, 60, 70, 80, 90] ); assert_eq!( - s.range((Included(&0), Unbounded)) + s.range::((Included(&0), Unbounded)) .map(|x| *x) .collect::>(), vec![0, 10, 20, 30, 40, 50, 60, 70, 80, 90] ); assert_eq!( - s.range((Excluded(&0), Unbounded)) + s.range::((Excluded(&0), Unbounded)) .map(|x| *x) .collect::>(), vec![10, 20, 30, 40, 50, 60, 70, 80, 90] ); assert_eq!( - s.range((Included(&25), Unbounded)) + s.range::((Included(&25), Unbounded)) .map(|x| *x) .collect::>(), vec![30, 40, 50, 60, 70, 80, 90] ); assert_eq!( - s.range((Excluded(&25), Unbounded)) + s.range::((Excluded(&25), Unbounded)) .map(|x| *x) .collect::>(), vec![30, 40, 50, 60, 70, 80, 90] ); assert_eq!( - s.range((Included(&70), Unbounded)) + s.range::((Included(&70), Unbounded)) .map(|x| *x) .collect::>(), vec![70, 80, 90] ); assert_eq!( - s.range((Excluded(&70), Unbounded)) + s.range::((Excluded(&70), Unbounded)) .map(|x| *x) .collect::>(), vec![80, 90] ); assert_eq!( - s.range((Included(&100), Unbounded)) + s.range::((Included(&100), Unbounded)) .map(|x| *x) .collect::>(), vec![] ); assert_eq!( - s.range((Excluded(&100), Unbounded)) + s.range::((Excluded(&100), Unbounded)) .map(|x| *x) .collect::>(), vec![] ); assert_eq!( - s.range((Unbounded, Included(&90))) + s.range::((Unbounded, Included(&90))) .map(|x| *x) .collect::>(), vec![0, 10, 20, 30, 40, 50, 60, 70, 80, 90] ); assert_eq!( - s.range((Unbounded, Excluded(&90))) + s.range::((Unbounded, Excluded(&90))) .map(|x| *x) .collect::>(), vec![0, 10, 20, 30, 40, 50, 60, 70, 80] ); assert_eq!( - s.range((Unbounded, Included(&25))) + s.range::((Unbounded, Included(&25))) .map(|x| *x) .collect::>(), vec![0, 10, 20] ); assert_eq!( - s.range((Unbounded, Excluded(&25))) + s.range::((Unbounded, Excluded(&25))) .map(|x| *x) .collect::>(), vec![0, 10, 20] ); assert_eq!( - s.range((Unbounded, Included(&70))) + s.range::((Unbounded, Included(&70))) .map(|x| *x) .collect::>(), vec![0, 10, 20, 30, 40, 50, 60, 70] ); assert_eq!( - s.range((Unbounded, Excluded(&70))) + s.range::((Unbounded, Excluded(&70))) .map(|x| *x) .collect::>(), vec![0, 10, 20, 30, 40, 50, 60] ); assert_eq!( - s.range((Unbounded, Included(&-1))) + s.range::((Unbounded, Included(&-1))) .map(|x| *x) .collect::>(), vec![] ); assert_eq!( - s.range((Unbounded, Excluded(&-1))) + s.range::((Unbounded, Excluded(&-1))) .map(|x| *x) .collect::>(), vec![] ); assert_eq!( - s.range((Included(&25), Included(&80))) + s.range::((Included(&25), Included(&80))) .map(|x| *x) .collect::>(), vec![30, 40, 50, 60, 70, 80] ); assert_eq!( - s.range((Included(&25), Excluded(&80))) + s.range::((Included(&25), Excluded(&80))) .map(|x| *x) .collect::>(), vec![30, 40, 50, 60, 70] ); assert_eq!( - s.range((Excluded(&25), Included(&80))) + s.range::((Excluded(&25), Included(&80))) .map(|x| *x) .collect::>(), vec![30, 40, 50, 60, 70, 80] ); assert_eq!( - s.range((Excluded(&25), Excluded(&80))) + s.range::((Excluded(&25), Excluded(&80))) .map(|x| *x) .collect::>(), vec![30, 40, 50, 60, 70] ); assert_eq!( - s.range((Included(&25), Included(&25))) + s.range::((Included(&25), Included(&25))) .map(|x| *x) .collect::>(), vec![] ); assert_eq!( - s.range((Included(&25), Excluded(&25))) + s.range::((Included(&25), Excluded(&25))) .map(|x| *x) .collect::>(), vec![] ); assert_eq!( - s.range((Excluded(&25), Included(&25))) + s.range::((Excluded(&25), Included(&25))) .map(|x| *x) .collect::>(), vec![] ); assert_eq!( - s.range((Excluded(&25), Excluded(&25))) + s.range::((Excluded(&25), Excluded(&25))) .map(|x| *x) .collect::>(), vec![] ); assert_eq!( - s.range((Included(&50), Included(&50))) + s.range::((Included(&50), Included(&50))) .map(|x| *x) .collect::>(), vec![50] ); assert_eq!( - s.range((Included(&50), Excluded(&50))) + s.range::((Included(&50), Excluded(&50))) .map(|x| *x) .collect::>(), vec![] ); assert_eq!( - s.range((Excluded(&50), Included(&50))) + s.range::((Excluded(&50), Included(&50))) .map(|x| *x) .collect::>(), vec![] ); assert_eq!( - s.range((Excluded(&50), Excluded(&50))) + s.range::((Excluded(&50), Excluded(&50))) .map(|x| *x) .collect::>(), vec![] ); assert_eq!( - s.range((Included(&100), Included(&-2))) + s.range::((Included(&100), Included(&-2))) .map(|x| *x) .collect::>(), vec![] ); assert_eq!( - s.range((Included(&100), Excluded(&-2))) + s.range::((Included(&100), Excluded(&-2))) .map(|x| *x) .collect::>(), vec![] ); assert_eq!( - s.range((Excluded(&100), Included(&-2))) + s.range::((Excluded(&100), Included(&-2))) .map(|x| *x) .collect::>(), vec![] ); assert_eq!( - s.range((Excluded(&100), Excluded(&-2))) + s.range::((Excluded(&100), Excluded(&-2))) .map(|x| *x) .collect::>(), vec![]