diff --git a/Cargo.toml b/Cargo.toml index c6fd471..e216777 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "skl" -version = "0.21.2" +version = "0.22.0" edition = "2021" rust-version = "1.81.0" repository = "https://github.com/al8n/skl" diff --git a/examples/multiple_maps.rs b/examples/multiple_maps.rs index af7b8de..282a685 100644 --- a/examples/multiple_maps.rs +++ b/examples/multiple_maps.rs @@ -1,7 +1,7 @@ use skl::{ generic::{ unique::{sync::SkipMap, Map}, - Builder, + Builder, DefaultComparator, }, Arena, }; @@ -25,7 +25,9 @@ fn main() { .with_capacity(1024 * 1024) .map_mut::, _>("multiple_maps.wal") .unwrap(); - let l2 = SkipMap::<[u8], [u8]>::create_from_allocator(l.allocator().clone()).unwrap(); + let l2 = + SkipMap::<[u8], [u8]>::create_from_allocator(l.allocator().clone(), DefaultComparator) + .unwrap(); let h2 = l2.header().copied().unwrap(); let t1 = std::thread::spawn(move || { @@ -56,7 +58,9 @@ fn main() { .with_capacity((1024 * 1024 * 2) as u32) .map_mut::, _>("multiple_maps.wal") .unwrap(); - let l2 = SkipMap::<[u8], [u8]>::open_from_allocator(header, l.allocator().clone()).unwrap(); + let l2 = + SkipMap::<[u8], [u8]>::open_from_allocator(header, l.allocator().clone(), DefaultComparator) + .unwrap(); assert_eq!(500, l.len()); assert_eq!(500, l2.len()); diff --git a/src/dynamic.rs b/src/dynamic.rs index f9fd6ed..acdfdc9 100644 --- a/src/dynamic.rs +++ b/src/dynamic.rs @@ -19,7 +19,10 @@ pub mod entry { pub use super::list::EntryRef; } -pub use dbutils::equivalentor::*; +pub use dbutils::equivalentor::{ + Ascend, Descend, DynComparator, DynEquivalentor, DynRangeComparator, StaticComparator, + StaticEquivalentor, StaticRangeComparator, +}; /// Value that can be converted from a byte slice. pub trait Value<'a>: sealed::Sealed<'a> {} diff --git a/src/dynamic/builder.rs b/src/dynamic/builder.rs index 42ad5e8..5653e0e 100644 --- a/src/dynamic/builder.rs +++ b/src/dynamic/builder.rs @@ -1,6 +1,6 @@ use core::mem; -use dbutils::equivalentor::{Ascend, Comparator}; +use dbutils::equivalentor::{Ascend, DynComparator}; use crate::{ allocator::Sealed, @@ -143,7 +143,7 @@ impl Builder { crate::__builder_opts!(dynamic::Builder); } -impl Builder { +impl> Builder { /// Create a new map which is backed by a `AlignedVec`. /// /// **Note:** The capacity stands for how many memory allocated, diff --git a/src/dynamic/builder/memmap.rs b/src/dynamic/builder/memmap.rs index b639e45..a5d7231 100644 --- a/src/dynamic/builder/memmap.rs +++ b/src/dynamic/builder/memmap.rs @@ -1,6 +1,6 @@ use core::mem; -use dbutils::equivalentor::Comparator; +use dbutils::equivalentor::DynComparator; use either::Either; use super::Builder; @@ -12,7 +12,7 @@ use crate::{ Arena, }; -impl Builder { +impl> Builder { /// Create a new map which is backed by a anonymous memory map. /// /// **What the difference between this method and [`Builder::alloc`]?** diff --git a/src/dynamic/list.rs b/src/dynamic/list.rs index 6063aab..5b1b70f 100644 --- a/src/dynamic/list.rs +++ b/src/dynamic/list.rs @@ -3,7 +3,7 @@ use core::{cmp, ptr::NonNull, sync::atomic::Ordering}; use among::Among; use dbutils::{ buffer::VacantBuffer, - equivalentor::{Ascend, Comparator}, + equivalentor::{Ascend, DynComparator}, }; use either::Either; use rarena_allocator::Allocator as _; @@ -312,7 +312,7 @@ where impl SkipList where A: Allocator, - C: Comparator, + C: DynComparator<[u8], [u8]>, R: RefCounter, { unsafe fn move_to_prev<'a, V>( @@ -1241,7 +1241,7 @@ where #[inline] fn compare(this: Either<&'a [u8], &'b [u8]>, other: &'a [u8], cmp: &C) -> cmp::Ordering where - C: Comparator, + C: DynComparator<[u8], [u8]>, { match this { Either::Left(key) | Either::Right(key) => cmp.compare(key, other), diff --git a/src/dynamic/list/api.rs b/src/dynamic/list/api.rs index f378f95..bc9c5b2 100644 --- a/src/dynamic/list/api.rs +++ b/src/dynamic/list/api.rs @@ -4,7 +4,7 @@ use core::{ ops::{Bound, RangeBounds}, }; -use dbutils::{buffer::VacantBuffer, equivalentor::Comparator}; +use dbutils::{buffer::VacantBuffer, equivalentor::DynComparator}; use rarena_allocator::Allocator as _; use crate::{ @@ -155,7 +155,7 @@ where impl SkipList where A: Allocator, - C: Comparator, + C: DynComparator<[u8], [u8]>, RC: RefCounter, { /// Returns `true` if the key exists in the map. diff --git a/src/dynamic/list/api/update.rs b/src/dynamic/list/api/update.rs index 2d7aea9..8e1e464 100644 --- a/src/dynamic/list/api/update.rs +++ b/src/dynamic/list/api/update.rs @@ -5,13 +5,13 @@ use super::{ use crate::KeyBuilder; use among::Among; use core::sync::atomic::Ordering; -use dbutils::{buffer::VacantBuffer, equivalentor::Comparator}; +use dbutils::{buffer::VacantBuffer, equivalentor::DynComparator}; use either::Either; impl SkipList where A: Allocator, - C: Comparator, + C: DynComparator<[u8], [u8]>, R: RefCounter, { /// Upserts a new key-value pair if it does not yet exist, if the key with the given version already exists, it will update the value. diff --git a/src/dynamic/list/entry.rs b/src/dynamic/list/entry.rs index 88e4cb8..91f57bc 100644 --- a/src/dynamic/list/entry.rs +++ b/src/dynamic/list/entry.rs @@ -4,7 +4,7 @@ use crate::{ ref_counter::RefCounter, Version, }; -use dbutils::equivalentor::Comparator; +use dbutils::equivalentor::DynComparator; /// An entry reference of the `SkipMap`. pub struct EntryRef<'a, V, C, A, R> @@ -121,7 +121,7 @@ where impl<'a, V, C, A, R> EntryRef<'a, V, C, A, R> where - C: Comparator, + C: DynComparator<[u8], [u8]>, A: Allocator, R: RefCounter, V: Value<'a> + 'a, diff --git a/src/dynamic/list/iterator.rs b/src/dynamic/list/iterator.rs index cb9fb0a..990d3f0 100644 --- a/src/dynamic/list/iterator.rs +++ b/src/dynamic/list/iterator.rs @@ -4,7 +4,7 @@ use core::{ borrow::Borrow, ops::{Bound, RangeBounds}, }; -use dbutils::equivalentor::{Comparator, RangeComparator}; +use dbutils::equivalentor::{DynComparator, DynRangeComparator}; /// An iterator over the skipmap (this iterator will yields all versions). The current state of the iterator can be cloned by /// simply value copying the struct. @@ -145,7 +145,7 @@ where impl<'a, V, A, RC, C, Q, R> Iter<'a, V, A, RC, C, Q, R> where A: Allocator, - C: Comparator, + C: DynComparator<[u8], [u8]>, RC: RefCounter, Q: ?Sized + Borrow<[u8]>, R: RangeBounds, @@ -373,7 +373,7 @@ where impl<'a, V, A, RC, C, Q, R> Iter<'a, V, A, RC, C, Q, R> where A: Allocator, - C: Comparator, + C: DynComparator<[u8], [u8]>, RC: RefCounter, Q: ?Sized + Borrow<[u8]>, R: RangeBounds, @@ -592,7 +592,7 @@ where impl<'a, V, A, RC, C, Q, R> Iterator for Iter<'a, V, A, RC, C, Q, R> where A: Allocator, - C: Comparator, + C: DynComparator<[u8], [u8]>, RC: RefCounter, Q: ?Sized + Borrow<[u8]>, R: RangeBounds, @@ -639,7 +639,7 @@ where impl<'a, V, A, RC, C, Q, R> DoubleEndedIterator for Iter<'a, V, A, RC, C, Q, R> where A: Allocator, - C: Comparator, + C: DynComparator<[u8], [u8]>, RC: RefCounter, Q: ?Sized + Borrow<[u8]>, R: RangeBounds, @@ -656,7 +656,11 @@ where } /// Helper function to check if a value is above a lower bound -fn above_lower_bound_compare(cmp: &C, bound: Bound<&[u8]>, other: &[u8]) -> bool { +fn above_lower_bound_compare>( + cmp: &C, + bound: Bound<&[u8]>, + other: &[u8], +) -> bool { match bound { Bound::Unbounded => true, Bound::Included(key) => cmp.compare(key, other).is_le(), @@ -665,7 +669,11 @@ fn above_lower_bound_compare(cmp: &C, bound: Bound<&[u8]>, other: } /// Helper function to check if a value is above a lower bound -fn above_lower_bound(cmp: &C, bound: Bound<&[u8]>, other: &[u8]) -> bool { +fn above_lower_bound>( + cmp: &C, + bound: Bound<&[u8]>, + other: &[u8], +) -> bool { match bound { Bound::Unbounded => true, Bound::Included(key) => cmp.compare(key, other).is_le(), @@ -674,7 +682,11 @@ fn above_lower_bound(cmp: &C, bound: Bound<&[u8]>, other: &[u8]) } /// Helper function to check if a value is below an upper bound -fn below_upper_bound_compare(cmp: &C, bound: Bound<&[u8]>, other: &[u8]) -> bool { +fn below_upper_bound_compare>( + cmp: &C, + bound: Bound<&[u8]>, + other: &[u8], +) -> bool { match bound { Bound::Unbounded => true, Bound::Included(key) => cmp.compare(key, other).is_ge(), @@ -683,7 +695,11 @@ fn below_upper_bound_compare(cmp: &C, bound: Bound<&[u8]>, other: } /// Helper function to check if a value is below an upper bound -fn below_upper_bound(cmp: &C, bound: Bound<&[u8]>, other: &[u8]) -> bool { +fn below_upper_bound>( + cmp: &C, + bound: Bound<&[u8]>, + other: &[u8], +) -> bool { match bound { Bound::Unbounded => true, Bound::Included(key) => cmp.compare(key, other).is_ge(), diff --git a/src/dynamic/multiple_version.rs b/src/dynamic/multiple_version.rs index bf03189..9efde31 100644 --- a/src/dynamic/multiple_version.rs +++ b/src/dynamic/multiple_version.rs @@ -7,7 +7,7 @@ use core::{ }; use among::Among; -use dbutils::{buffer::VacantBuffer, equivalentor::Comparator}; +use dbutils::{buffer::VacantBuffer, equivalentor::DynComparator}; use either::Either; use crate::{ @@ -21,7 +21,7 @@ use super::list::{iterator::Iter, EntryRef}; /// Implementations for single-threaded environments. pub mod unsync { - use dbutils::equivalentor::{Ascend, Comparator}; + use dbutils::equivalentor::{Ascend, DynComparator}; pub use crate::unsync::{multiple_version::Allocator, RefCounter}; @@ -83,7 +83,7 @@ pub mod unsync { } } - impl super::Map for SkipMap { + impl> super::Map for SkipMap { type Allocator = Allocator; type Comparator = C; type RefCounter = RefCounter; @@ -92,7 +92,7 @@ pub mod unsync { /// Implementations for concurrent environments. pub mod sync { - use dbutils::equivalentor::{Ascend, Comparator}; + use dbutils::equivalentor::{Ascend, DynComparator}; pub use crate::sync::{multiple_version::Allocator, RefCounter}; @@ -181,7 +181,7 @@ pub mod sync { } } - impl super::Map for SkipMap { + impl> super::Map for SkipMap { type Allocator = Allocator; type RefCounter = RefCounter; type Comparator = C; @@ -202,7 +202,7 @@ where /// The allocator type used to allocate nodes in the map. type Allocator: Allocator; /// The comparator type used to compare keys in the map. - type Comparator: Comparator; + type Comparator: DynComparator<[u8], [u8]>; /// The reference counter type of the map. type RefCounter: RefCounter; diff --git a/src/dynamic/unique.rs b/src/dynamic/unique.rs index df2a009..21907c0 100644 --- a/src/dynamic/unique.rs +++ b/src/dynamic/unique.rs @@ -5,7 +5,7 @@ use core::{ }; use among::Among; -use dbutils::{buffer::VacantBuffer, equivalentor::Comparator}; +use dbutils::{buffer::VacantBuffer, equivalentor::DynComparator}; use either::Either; use crate::{ @@ -19,7 +19,7 @@ use super::list::{iterator::Iter, EntryRef}; /// Implementations for single-threaded environments. pub mod unsync { - use dbutils::equivalentor::{Ascend, Comparator}; + use dbutils::equivalentor::{Ascend, DynComparator}; pub use crate::unsync::{map::Allocator, RefCounter}; @@ -82,7 +82,7 @@ pub mod unsync { } } - impl super::Map for SkipMap { + impl> super::Map for SkipMap { type Allocator = Allocator; type Comparator = C; type RefCounter = RefCounter; @@ -91,7 +91,7 @@ pub mod unsync { /// Implementations for concurrent environments. pub mod sync { - use dbutils::equivalentor::{Ascend, Comparator}; + use dbutils::equivalentor::{Ascend, DynComparator}; pub use crate::sync::{map::Allocator, RefCounter}; @@ -177,7 +177,7 @@ pub mod sync { } } - impl super::Map for SkipMap { + impl> super::Map for SkipMap { type Allocator = Allocator; type Comparator = C; type RefCounter = RefCounter; @@ -198,7 +198,7 @@ where /// The allocator used to allocate nodes in the `SkipMap`. type Allocator: Allocator; /// The comparator used to compare keys in the `SkipMap`. - type Comparator: Comparator; + type Comparator: DynComparator<[u8], [u8]>; /// The reference counter of the `SkipMap`. type RefCounter: RefCounter; diff --git a/src/generic.rs b/src/generic.rs index ce472e0..631ba8e 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -19,9 +19,11 @@ pub mod entry { pub use builder::Builder; -use dbutils::equivalentor::{Comparator, Equivalentor}; -pub use dbutils::{equivalent::*, types::*}; - +pub use dbutils::{ + equivalent::*, + equivalentor::{Comparator, Equivalentor, RangeComparator}, + types::*, +}; /// The default stateless comparator. #[derive(Default, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -32,18 +34,19 @@ impl Equivalentor for DefaultComparator { fn equivalent(&self, a: &A, b: &B) -> bool where A: ?Sized, - B: ?Sized + Equivalent + B: ?Sized + Equivalent, { - b.equivalent(a) + b.equivalent(a) } } impl Comparator for DefaultComparator { #[inline] fn compare(&self, a: &A, b: &B) -> core::cmp::Ordering - where - A: ?Sized, - B: ?Sized + Comparable { + where + A: ?Sized, + B: ?Sized + Comparable, + { b.compare(a).reverse() } } diff --git a/src/generic/builder.rs b/src/generic/builder.rs index 5a66475..a2b7c01 100644 --- a/src/generic/builder.rs +++ b/src/generic/builder.rs @@ -1,6 +1,6 @@ use core::mem; -use super::super::Options; +use super::{super::Options, DefaultComparator}; use crate::{ allocator::Sealed, error::Error, @@ -16,8 +16,9 @@ mod memmap; /// A builder for creating a generic key-value `SkipMap`. #[derive(Debug, Clone)] -pub struct Builder { +pub struct Builder { options: Options, + cmp: C, } impl Default for Builder { @@ -27,16 +28,19 @@ impl Default for Builder { } } -impl From for Builder { +impl From for Builder { #[inline] fn from(options: Options) -> Self { - Self { options } + Self { + options, + cmp: Default::default(), + } } } -impl From for Options { +impl From> for Options { #[inline] - fn from(builder: Builder) -> Self { + fn from(builder: Builder) -> Self { builder.options } } @@ -55,6 +59,42 @@ impl Builder { pub const fn new() -> Self { Self { options: Options::new(), + cmp: DefaultComparator, + } + } +} + +impl Builder { + /// Get the comparator of the builder. + /// + /// ## Example + /// + /// ```rust + /// use skl::generic::Builder; + /// + /// let builder = Builder::new().comparator(); + /// ``` + #[inline] + pub const fn comparator(&self) -> &C { + &self.cmp + } + + /// Set the comparator for the builder. + /// + /// ## Example + /// + /// ```rust + /// use skl::generic::{Builder, DefaultComparator}; + /// + /// let builder = Builder::new().with_comparator(DefaultComparator); + /// + /// assert_eq!(builder.comparator(), &DefaultComparator); + /// ``` + #[inline] + pub fn with_comparator(self, cmp: NC) -> Builder { + Builder { + options: self.options, + cmp, } } @@ -91,7 +131,7 @@ impl Builder { crate::__builder_opts!(generic::Builder); } -impl Builder { +impl Builder { /// Create a new map which is backed by a `AlignedVec`. /// /// **Note:** The capacity stands for how many memory allocated, @@ -122,17 +162,17 @@ impl Builder { pub fn alloc(self) -> Result where T: Arena, - T::Constructable: Constructable, + T::Constructable: Constructable, { let node_align = mem::align_of::<<::Allocator as Sealed>::Node>(); - let Builder { options } = self; + let Builder { options, cmp } = self; options .to_arena_options() .with_maximum_alignment(node_align) .alloc::<<::Allocator as Sealed>::Allocator>() .map_err(Into::into) - .and_then(|arena| T::construct(arena, options, false, ())) + .and_then(|arena| T::construct(arena, options, false, cmp)) } } diff --git a/src/generic/builder/memmap.rs b/src/generic/builder/memmap.rs index e89782e..52a82ed 100644 --- a/src/generic/builder/memmap.rs +++ b/src/generic/builder/memmap.rs @@ -11,7 +11,7 @@ use crate::{ Arena, }; -impl Builder { +impl Builder { /// Create a new map which is backed by a anonymous memory map. /// /// **What the difference between this method and [`Builder::alloc`]?** @@ -41,18 +41,18 @@ impl Builder { pub fn map_anon(self) -> std::io::Result where T: Arena, - T::Constructable: Constructable, + T::Constructable: Constructable, { let node_align = mem::align_of::<<::Allocator as Sealed>::Node>(); - let Builder { options } = self; + let Self { options, cmp } = self; options .to_arena_options() .with_maximum_alignment(node_align) .map_anon::<<::Allocator as Sealed>::Allocator>() .map_err(Into::into) - .and_then(|arena| T::construct(arena, options, false, ()).map_err(invalid_data)) + .and_then(|arena| T::construct(arena, options, false, cmp).map_err(invalid_data)) } /// Opens a read-only map which backed by file-backed memory map. @@ -70,7 +70,7 @@ impl Builder { pub unsafe fn map(self, path: P) -> std::io::Result where T: Arena, - T::Constructable: Constructable, + T::Constructable: Constructable, P: AsRef, { self @@ -96,7 +96,7 @@ impl Builder { ) -> Result> where T: Arena, - T::Constructable: Constructable, + T::Constructable: Constructable, PB: FnOnce() -> Result, { use crate::allocator::Meta as _; @@ -104,7 +104,7 @@ impl Builder { let node_align = mem::align_of::<<::Allocator as Sealed>::Node>(); - let Builder { options } = self; + let Self { options, cmp } = self; let magic_version = options.magic_version(); #[allow(clippy::bind_instead_of_map)] @@ -120,7 +120,7 @@ impl Builder { .with_maximum_alignment(node_align) .map_with_path_builder::<<::Allocator as Sealed>::Allocator, _, _>(path_builder) .and_then(|arena| { - T::construct(arena, options, true, ()) + T::construct(arena, options, true, cmp) .map_err(invalid_data) .and_then(|map| { let flags = map.meta().flags(); @@ -158,7 +158,7 @@ impl Builder { pub unsafe fn map_mut(self, path: P) -> std::io::Result where T: Arena, - T::Constructable: Constructable, + T::Constructable: Constructable, P: AsRef, { self @@ -183,14 +183,14 @@ impl Builder { ) -> Result> where T: Arena, - T::Constructable: Constructable, + T::Constructable: Constructable, PB: FnOnce() -> Result, { use crate::allocator::Meta as _; let node_align = mem::align_of::<<::Allocator as Sealed>::Node>(); - let Builder { options } = self; + let Self { options, cmp } = self; let magic_version = options.magic_version(); let path = path_builder().map_err(Either::Left)?; let exist = path.exists(); @@ -203,7 +203,7 @@ impl Builder { .map_mut::<<::Allocator as Sealed>::Allocator, _>(path) .map_err(Either::Right) .and_then(|arena| { - T::construct(arena, options, exist, ()) + T::construct(arena, options, exist, cmp) .map_err(invalid_data) .and_then(|map| { let flags = map.meta().flags(); diff --git a/src/generic/list.rs b/src/generic/list.rs index 7bf249c..593ff37 100644 --- a/src/generic/list.rs +++ b/src/generic/list.rs @@ -2,7 +2,10 @@ use core::{cmp, marker::PhantomData, ptr::NonNull, sync::atomic::Ordering}; use among::Among; use dbutils::{ - buffer::VacantBuffer, equivalent::Comparable, equivalentor::Comparator, types::{KeyRef, LazyRef, MaybeStructured, Type} + buffer::VacantBuffer, + equivalent::Comparable, + equivalentor::Comparator, + types::{KeyRef, LazyRef, MaybeStructured, Type}, }; use either::Either; use rarena_allocator::Allocator as _; @@ -596,7 +599,11 @@ where // let next_node = next.as_ref(&self.arena); let next_key = ty_ref::(next.get_key(&self.arena)); - let cmp = self.cmp.compare(&next_key, key).reverse().then_with(|| next.version().cmp(&version)); + let cmp = self + .cmp + .compare(&next_key, key) + .reverse() + .then_with(|| next.version().cmp(&version)); match cmp { cmp::Ordering::Greater => { diff --git a/src/generic/list/api.rs b/src/generic/list/api.rs index 20a81ef..478003a 100644 --- a/src/generic/list/api.rs +++ b/src/generic/list/api.rs @@ -4,7 +4,10 @@ use core::{ }; use dbutils::{ - buffer::VacantBuffer, equivalent::{Comparable, Equivalent}, equivalentor::Comparator, types::{KeyRef, LazyRef, Type} + buffer::VacantBuffer, + equivalent::{Comparable, Equivalent}, + equivalentor::Comparator, + types::{KeyRef, LazyRef, Type}, }; use rarena_allocator::Allocator as _; diff --git a/src/generic/list/api/update.rs b/src/generic/list/api/update.rs index 739dacc..8afde2e 100644 --- a/src/generic/list/api/update.rs +++ b/src/generic/list/api/update.rs @@ -2,7 +2,9 @@ use core::sync::atomic::Ordering; use among::Among; use dbutils::{ - buffer::VacantBuffer, equivalentor::Comparator, types::{KeyRef, LazyRef, MaybeStructured, Type} + buffer::VacantBuffer, + equivalentor::Comparator, + types::{KeyRef, LazyRef, MaybeStructured, Type}, }; use either::Either; diff --git a/src/generic/list/entry.rs b/src/generic/list/entry.rs index 9af6e79..6fc8d30 100644 --- a/src/generic/list/entry.rs +++ b/src/generic/list/entry.rs @@ -1,4 +1,7 @@ -use dbutils::{equivalentor::Comparator, types::{KeyRef, LazyRef, Type}}; +use dbutils::{ + equivalentor::Comparator, + types::{KeyRef, LazyRef, Type}, +}; use super::{RefCounter, SkipList}; use crate::{ diff --git a/src/generic/list/iterator.rs b/src/generic/list/iterator.rs index f55e55f..2d7ffce 100644 --- a/src/generic/list/iterator.rs +++ b/src/generic/list/iterator.rs @@ -1,7 +1,9 @@ use core::ops::{Bound, RangeBounds}; use dbutils::{ - equivalent::Comparable, equivalentor::{Comparator, RangeComparator}, types::{KeyRef, Type} + equivalent::Comparable, + equivalentor::{Comparator, RangeComparator}, + types::{KeyRef, Type}, }; use crate::{allocator::Node, generic::GenericValue}; diff --git a/src/generic/multiple_version.rs b/src/generic/multiple_version.rs index 1556266..e00d77a 100644 --- a/src/generic/multiple_version.rs +++ b/src/generic/multiple_version.rs @@ -5,15 +5,24 @@ use core::{ use among::Among; use dbutils::{ - buffer::VacantBuffer, equivalent::Comparable, equivalentor::Comparator, types::{KeyRef, LazyRef, MaybeStructured, Type} + buffer::VacantBuffer, + equivalent::Comparable, + equivalentor::Comparator, + types::{KeyRef, LazyRef, MaybeStructured, Type}, }; use either::Either; use crate::{ - allocator::{Allocator, Sealed, WithVersion}, error::Error, ref_counter::RefCounter, Arena, Header, Height, KeyBuilder, ValueBuilder, Version + allocator::{Allocator, Sealed, WithVersion}, + error::Error, + ref_counter::RefCounter, + Arena, Header, Height, KeyBuilder, ValueBuilder, Version, }; -use super::{list::{iterator::Iter, EntryRef}, DefaultComparator}; +use super::{ + list::{iterator::Iter, EntryRef}, + DefaultComparator, +}; /// Implementations for single-threaded environments. pub mod unsync { @@ -27,16 +36,20 @@ pub mod unsync { crate::__generic_multiple_version_map_tests!("unsync_multiple_version_map": super::SkipMap<[u8], [u8]>); } - type SkipList = super::super::list::SkipList; + type SkipList = + super::super::list::SkipList; /// Iterator over the [`SkipMap`]. - pub type Iter<'a, K, L, C = DefaultComparator> = super::super::iter::Iter<'a, K, L, Allocator, RefCounter, C>; + pub type Iter<'a, K, L, C = DefaultComparator> = + super::super::iter::Iter<'a, K, L, Allocator, RefCounter, C>; /// Iterator over a subset of the [`SkipMap`]. - pub type Range<'a, K, L, Q, R, C = DefaultComparator> = super::super::iter::Iter<'a, K, L, Allocator, RefCounter, C, Q, R>; + pub type Range<'a, K, L, Q, R, C = DefaultComparator> = + super::super::iter::Iter<'a, K, L, Allocator, RefCounter, C, Q, R>; /// The entry reference of the [`SkipMap`]. - pub type Entry<'a, K, L, C = DefaultComparator> = super::super::entry::EntryRef<'a, K, L, Allocator, RefCounter, C>; + pub type Entry<'a, K, L, C = DefaultComparator> = + super::super::entry::EntryRef<'a, K, L, Allocator, RefCounter, C>; /// A fast, ARENA based `SkipMap` that supports multiple versions, forward and backward iteration. /// @@ -95,8 +108,8 @@ pub mod unsync { pub mod sync { use dbutils::equivalentor::Comparator; + use crate::generic::DefaultComparator; pub use crate::sync::{multiple_version::Allocator, RefCounter}; - use crate::{generic::DefaultComparator, traits::List}; #[cfg(any(all(test, not(miri)), all_skl_tests, test_generic_sync_versioned,))] mod tests { @@ -130,16 +143,20 @@ pub mod sync { crate::__generic_multiple_version_map_tests!(go "sync_multiple_version_map": super::SkipMap<[u8], [u8]> => crate::tests::generic::TEST_OPTIONS_WITH_PESSIMISTIC_FREELIST); } - type SkipList = super::super::list::SkipList; + type SkipList = + super::super::list::SkipList; /// Iterator over the [`SkipMap`]. - pub type Iter<'a, K, L, C = DefaultComparator> = super::super::iter::Iter<'a, K, L, Allocator, RefCounter, C>; + pub type Iter<'a, K, L, C = DefaultComparator> = + super::super::iter::Iter<'a, K, L, Allocator, RefCounter, C>; /// Iterator over a subset of the [`SkipMap`]. - pub type Range<'a, K, L, Q, R, C = DefaultComparator> = super::super::iter::Iter<'a, K, L, Allocator, RefCounter, C, Q, R>; + pub type Range<'a, K, L, Q, R, C = DefaultComparator> = + super::super::iter::Iter<'a, K, L, Allocator, RefCounter, C, Q, R>; /// The entry reference of the [`SkipMap`]. - pub type Entry<'a, K, L, C = DefaultComparator> = super::super::entry::EntryRef<'a, K, L, Allocator, RefCounter, C>; + pub type Entry<'a, K, L, C = DefaultComparator> = + super::super::entry::EntryRef<'a, K, L, Allocator, RefCounter, C>; /// A fast, lock-free, thread-safe ARENA based `SkipMap` that supports multiple versions, forward and backward iteration. /// @@ -192,38 +209,6 @@ pub mod sync { type Allocator = Allocator; type RefCounter = RefCounter; } - - impl SkipMap - where - K: ?Sized + 'static, - V: ?Sized + 'static, - C: Comparator + 'static, - { - /// Try creates from a `SkipMap` from an allocator directly. - /// - /// This method is not the ideal constructor, it is recommended to use [`Builder`](super::Builder) to create a `SkipMap`, - /// if you are not attempting to create multiple `SkipMap`s on the same allocator. - /// - /// Besides, the only way to reconstruct `SkipMap`s created by this method is to use the [`open_from_allocator(header: Header, arena: Self::Allocator, cmp: Self::Comparator)`](Self::open_from_allocator) method, - /// users must save the header to reconstruct the `SkipMap` by their own. - /// The header can be obtained by calling [`header`](Map::header) method. - #[inline] - pub fn create_from_allocator(arena: >::Allocator, cmp: C) -> Result { - ::try_create_from_allocator(arena, cmp) - } - - /// Try open a `SkipMap` from an allocator directly. - /// - /// See documentation for [`create_from_allocator`](Self::create_from_allocator) for more information. - /// - /// ## Safety - /// - The `header` must be the same as the one obtained from `SkipMap` when it was created. - /// - The `K` and `V` types must be the same as the types used to create the map. - #[inline] - pub unsafe fn open_from_allocator(header: super::Header, arena: >::Allocator, cmp: C) -> Result { - ::try_open_from_allocator(arena, cmp, header) - } - } } /// A fast, ARENA based `SkipMap` that supports multiple versions, forward and backward iteration. @@ -243,6 +228,35 @@ where /// The reference counter type used in the map. type RefCounter: RefCounter; + /// Try creates from a `SkipMap` from an allocator directly. + /// + /// This method is not the ideal constructor, it is recommended to use [`Builder`](super::Builder) to create a `SkipMap`, + /// if you are not attempting to create multiple `SkipMap`s on the same allocator. + /// + /// Besides, the only way to reconstruct `SkipMap`s created by this method is to use the [`open_from_allocator(header: Header, arena: Self::Allocator, cmp: Self::Comparator)`](Map::open_from_allocator) method, + /// users must save the header to reconstruct the `SkipMap` by their own. + /// The header can be obtained by calling [`header`](Map::header) method. + #[inline] + fn create_from_allocator(arena: Self::Allocator, cmp: C) -> Result { + Self::try_create_from_allocator(arena, cmp) + } + + /// Try open a `SkipMap` from an allocator directly. + /// + /// See documentation for [`create_from_allocator`](Map::create_from_allocator) for more information. + /// + /// ## Safety + /// - The `header` must be the same as the one obtained from `SkipMap` when it was created. + /// - The `K` and `V` types must be the same as the types used to create the map. + #[inline] + unsafe fn open_from_allocator( + header: Header, + arena: Self::Allocator, + cmp: C, + ) -> Result { + Self::try_open_from_allocator(arena, cmp, header) + } + /// Returns the header of the `SkipMap`, which can be used to reconstruct the `SkipMap`. /// /// By default, `SkipMap` will allocate meta, head node, and tail node in the ARENA, diff --git a/src/generic/unique.rs b/src/generic/unique.rs index b65e552..c67a0e8 100644 --- a/src/generic/unique.rs +++ b/src/generic/unique.rs @@ -5,7 +5,10 @@ use core::{ use among::Among; use dbutils::{ - buffer::VacantBuffer, equivalent::Comparable, equivalentor::Comparator, types::{KeyRef, LazyRef, MaybeStructured, Type} + buffer::VacantBuffer, + equivalent::Comparable, + equivalentor::Comparator, + types::{KeyRef, LazyRef, MaybeStructured, Type}, }; use either::Either; @@ -16,7 +19,10 @@ use crate::{ Arena, Header, Height, KeyBuilder, ValueBuilder, MIN_VERSION, }; -use super::{list::{iterator::Iter, EntryRef}, DefaultComparator}; +use super::{ + list::{iterator::Iter, EntryRef}, + DefaultComparator, +}; /// Implementations for single-threaded environments. pub mod unsync { @@ -30,10 +36,12 @@ pub mod unsync { crate::__generic_map_tests!("unsync_map": super::SkipMap<[u8], [u8]>); } - type SkipList = super::super::list::SkipList; + type SkipList = + super::super::list::SkipList; /// Iterator over the [`SkipMap`]. - pub type Iter<'a, K, V, C = DefaultComparator> = super::super::iter::Iter<'a, K, LazyRef<'a, V>, Allocator, RefCounter, C>; + pub type Iter<'a, K, V, C = DefaultComparator> = + super::super::iter::Iter<'a, K, LazyRef<'a, V>, Allocator, RefCounter, C>; /// Iterator over a subset of the [`SkipMap`]. pub type Range<'a, K, V, Q, R, C = DefaultComparator> = @@ -100,7 +108,7 @@ pub mod sync { use dbutils::types::LazyRef; use crate::generic::DefaultComparator; -pub use crate::sync::{map::Allocator, RefCounter}; + pub use crate::sync::{map::Allocator, RefCounter}; #[cfg(any(all(test, not(miri)), all_skl_tests, test_generic_sync_map,))] mod tests { @@ -130,10 +138,12 @@ pub use crate::sync::{map::Allocator, RefCounter}; crate::__generic_map_tests!(go "sync_map": super::SkipMap<[u8], [u8]> => crate::tests::generic::TEST_OPTIONS_WITH_PESSIMISTIC_FREELIST); } - type SkipList = super::super::list::SkipList; + type SkipList = + super::super::list::SkipList; /// Iterator over the [`SkipMap`]. - pub type Iter<'a, K, V, C = DefaultComparator> = super::super::iter::Iter<'a, K, LazyRef<'a, V>, Allocator, RefCounter, C>; + pub type Iter<'a, K, V, C = DefaultComparator> = + super::super::iter::Iter<'a, K, LazyRef<'a, V>, Allocator, RefCounter, C>; /// Iterator over a subset of the [`SkipMap`]. pub type Range<'a, K, V, Q, R, C = DefaultComparator> = @@ -222,8 +232,8 @@ where /// users must save the header to reconstruct the `SkipMap` by their own. /// The header can be obtained by calling [`header`](Map::header) method. #[inline] - fn create_from_allocator(arena: Self::Allocator) -> Result { - Self::try_create_from_allocator(arena, ()) + fn create_from_allocator(arena: Self::Allocator, cmp: C) -> Result { + Self::try_create_from_allocator(arena, cmp) } /// Try open a `SkipMap` from an allocator directly. @@ -234,8 +244,12 @@ where /// - The `header` must be the same as the one obtained from `SkipMap` when it was created. /// - The `K` and `V` types must be the same as the types used to create the map. #[inline] - unsafe fn open_from_allocator(header: Header, arena: Self::Allocator) -> Result { - Self::try_open_from_allocator(arena, (), header) + unsafe fn open_from_allocator( + header: Header, + arena: Self::Allocator, + cmp: C, + ) -> Result { + Self::try_open_from_allocator(arena, cmp, header) } /// Returns the header of the `SkipMap`, which can be used to reconstruct the `SkipMap`. diff --git a/src/lib.rs b/src/lib.rs index 3a62281..183124b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,8 +19,8 @@ extern crate std; mod allocator; pub use allocator::GenericAllocator; -// /// The dynamic key-value type `SkipMap`s. -// pub mod dynamic; +/// The dynamic key-value type `SkipMap`s. +pub mod dynamic; /// The generic key-value type `SkipMap`s. pub mod generic; diff --git a/src/tests.rs b/src/tests.rs index 5b88e15..8b225a3 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -16,21 +16,21 @@ ))] pub mod generic; -// #[cfg(any( -// all(test, not(miri)), -// all_skl_tests, -// test_dynamic_unsync_map, -// test_dynamic_unsync_versioned, -// test_dynamic_sync_map, -// test_dynamic_sync_versioned, -// test_dynamic_sync_map_concurrent, -// test_dynamic_sync_multiple_version_concurrent, -// test_dynamic_sync_map_concurrent_with_optimistic_freelist, -// test_dynamic_sync_multiple_version_concurrent_with_optimistic_freelist, -// test_dynamic_sync_map_concurrent_with_pessimistic_freelist, -// test_dynamic_sync_multiple_version_concurrent_with_pessimistic_freelist, -// ))] -// pub mod dynamic; +#[cfg(any( + all(test, not(miri)), + all_skl_tests, + test_dynamic_unsync_map, + test_dynamic_unsync_versioned, + test_dynamic_sync_map, + test_dynamic_sync_versioned, + test_dynamic_sync_map_concurrent, + test_dynamic_sync_multiple_version_concurrent, + test_dynamic_sync_map_concurrent_with_optimistic_freelist, + test_dynamic_sync_multiple_version_concurrent_with_optimistic_freelist, + test_dynamic_sync_map_concurrent_with_pessimistic_freelist, + test_dynamic_sync_multiple_version_concurrent_with_pessimistic_freelist, +))] +pub mod dynamic; pub(crate) const KB: usize = 1 << 10; const ARENA_SIZE: usize = 1 << 20; diff --git a/src/tests/generic/map.rs b/src/tests/generic/map.rs index 05d7637..4a605e6 100644 --- a/src/tests/generic/map.rs +++ b/src/tests/generic/map.rs @@ -367,7 +367,8 @@ where #[cfg(miri)] const N: usize = 100; - let l2 = M::create_from_allocator(l.allocator().clone()).unwrap(); + let l2 = + M::create_from_allocator(l.allocator().clone(), crate::generic::DefaultComparator).unwrap(); for i in (0..N / 2).rev() { let l = l.clone(); @@ -1195,7 +1196,8 @@ where .with_capacity(ARENA_SIZE as u32) .map_mut::(&p) .unwrap(); - let l2 = M::create_from_allocator(l.allocator().clone()).unwrap(); + let l2 = + M::create_from_allocator(l.allocator().clone(), crate::generic::DefaultComparator).unwrap(); let h2 = l2.header().copied().unwrap(); let t1 = std::thread::spawn(move || { @@ -1226,7 +1228,12 @@ where .with_capacity((ARENA_SIZE * 2) as u32) .map_mut::(&p) .unwrap(); - let l2 = M::open_from_allocator(header, l.allocator().clone()).unwrap(); + let l2 = M::open_from_allocator( + header, + l.allocator().clone(), + crate::generic::DefaultComparator, + ) + .unwrap(); assert_eq!(500, l.len()); assert_eq!(500, l2.len()); diff --git a/src/tests/generic/multiple_version.rs b/src/tests/generic/multiple_version.rs index ccdb19f..ba8fed4 100644 --- a/src/tests/generic/multiple_version.rs +++ b/src/tests/generic/multiple_version.rs @@ -748,7 +748,8 @@ where #[cfg(miri)] const N: usize = 100; - let l2 = M::create_from_allocator(l.allocator().clone()).unwrap(); + let l2 = + M::create_from_allocator(l.allocator().clone(), crate::generic::DefaultComparator).unwrap(); for i in (0..N / 2).rev() { let l = l.clone(); @@ -1814,7 +1815,8 @@ where .with_capacity(ARENA_SIZE as u32) .map_mut::(&p) .unwrap(); - let l2 = M::create_from_allocator(l.allocator().clone()).unwrap(); + let l2 = + M::create_from_allocator(l.allocator().clone(), crate::generic::DefaultComparator).unwrap(); let h2 = l2.header().copied().unwrap(); let t1 = std::thread::spawn(move || { @@ -1845,7 +1847,12 @@ where .with_capacity((ARENA_SIZE * 2) as u32) .map_mut::(&p) .unwrap(); - let l2 = M::open_from_allocator(header, l.allocator().clone()).unwrap(); + let l2 = M::open_from_allocator( + header, + l.allocator().clone(), + crate::generic::DefaultComparator, + ) + .unwrap(); assert_eq!(500, l.len()); assert_eq!(500, l2.len());