Make st idx generic on alloc strategy

next
Sayan Nandan 2 years ago
parent 3eb00f892f
commit b21162c4dc
No known key found for this signature in database
GPG Key ID: 42EEDF4AE9D96B54

@ -0,0 +1,30 @@
/*
* Created on Sun Jan 29 2023
*
* This file is a part of Skytable
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
* NoSQL database written by Sayan Nandan ("the Author") with the
* vision to provide flexibility in data modelling without compromising
* on performance, queryability or scalability.
*
* Copyright (c) 2023, Sayan Nandan <ohsayan@outlook.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
use std::hash::BuildHasher;
pub trait AsHasher: BuildHasher + Default {}
impl<T> AsHasher for T where T: BuildHasher + Default {}

@ -24,6 +24,7 @@
* *
*/ */
mod meta;
mod mtchm; mod mtchm;
mod stdhm; mod stdhm;
mod stord; mod stord;
@ -34,9 +35,8 @@ use super::sync::atm::Guard;
use core::{borrow::Borrow, hash::Hash}; use core::{borrow::Borrow, hash::Hash};
// re-exports // re-exports
pub type IndexSTSeq<K, V, S> = stord::IndexSTSeqDll<K, V, S>; pub type IndexSTSeqCns<K, V> = stord::IndexSTSeqDll<K, V, stord::config::ConservativeConfig<K, V>>;
pub type IndexSTSeqDef<K, V> = IndexSTSeq<K, V, IndexSTSeqHasher>; pub type IndexSTSeqLib<K, V> = stord::IndexSTSeqDll<K, V, stord::config::LiberalConfig<K, V>>;
pub type IndexSTSeqHasher = stord::IndexSTSeqDllHasher;
pub type IndexMTRC<K, V> = mtchm::imp::ChmArc<K, V, mtchm::meta::DefConfig>; pub type IndexMTRC<K, V> = mtchm::imp::ChmArc<K, V, mtchm::meta::DefConfig>;
pub type IndexMTCp<K, V> = mtchm::imp::ChmCopy<K, V, mtchm::meta::DefConfig>; pub type IndexMTCp<K, V> = mtchm::imp::ChmCopy<K, V, mtchm::meta::DefConfig>;

@ -24,8 +24,8 @@
* *
*/ */
use super::super::{super::mem::VInline, AsKeyClone}; use super::super::{super::mem::VInline, meta::AsHasher, AsKeyClone};
use std::{collections::hash_map::RandomState, hash::BuildHasher, sync::Arc}; use std::{collections::hash_map::RandomState, sync::Arc};
const LNODE_STACK: usize = 2; const LNODE_STACK: usize = 2;
pub type DefConfig = Config2B<RandomState>; pub type DefConfig = Config2B<RandomState>;
@ -68,8 +68,6 @@ pub trait Key: AsKeyClone + 'static {}
impl<T> Key for T where T: AsKeyClone + 'static {} impl<T> Key for T where T: AsKeyClone + 'static {}
pub trait Value: Clone + 'static {} pub trait Value: Clone + 'static {}
impl<T> Value for T where T: Clone + 'static {} impl<T> Value for T where T: Clone + 'static {}
pub trait AsHasher: BuildHasher + Default {}
impl<T> AsHasher for T where T: BuildHasher + Default {}
pub trait TreeElement: Clone + 'static { pub trait TreeElement: Clone + 'static {
type Key: Key; type Key: Key;

@ -0,0 +1,125 @@
/*
* Created on Sun Jan 29 2023
*
* This file is a part of Skytable
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
* NoSQL database written by Sayan Nandan ("the Author") with the
* vision to provide flexibility in data modelling without compromising
* on performance, queryability or scalability.
*
* Copyright (c) 2023, Sayan Nandan <ohsayan@outlook.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
use super::{super::meta::AsHasher, IndexSTSeqDllNode, IndexSTSeqDllNodePtr};
use std::{collections::hash_map::RandomState, marker::PhantomData, ptr};
pub struct LiberalStrategy<K, V> {
f: *mut IndexSTSeqDllNode<K, V>,
}
impl<K, V> AllocStrategy<K, V> for LiberalStrategy<K, V> {
const NEW: Self = Self { f: ptr::null_mut() };
const METRIC_REFRESH: bool = true;
#[inline(always)]
unsafe fn free(&mut self, n: *mut IndexSTSeqDllNode<K, V>) {
(*n).n = self.f;
self.f = n;
}
#[inline(always)]
fn alloc(
&mut self,
node: IndexSTSeqDllNode<K, V>,
refresh_metric: &mut bool,
) -> IndexSTSeqDllNodePtr<K, V> {
if self.f.is_null() {
IndexSTSeqDllNode::alloc_box(node)
} else {
*refresh_metric = true;
unsafe {
// UNSAFE(@ohsayan): Safe because we already did a nullptr check
let f = self.f;
self.f = (*self.f).n;
ptr::write(f, node);
IndexSTSeqDllNodePtr::new_unchecked(f)
}
}
}
#[inline(always)]
fn cleanup(&mut self) {
unsafe {
// UNSAFE(@ohsayan): All nullck
let mut c = self.f;
while !c.is_null() {
let nx = (*c).n;
IndexSTSeqDllNode::dealloc_headless(c);
c = nx;
}
}
self.f = ptr::null_mut();
}
}
pub struct ConservativeStrategy<K, V> {
_d: PhantomData<IndexSTSeqDllNodePtr<K, V>>,
}
impl<K, V> AllocStrategy<K, V> for ConservativeStrategy<K, V> {
const NEW: Self = Self { _d: PhantomData };
const METRIC_REFRESH: bool = false;
#[inline(always)]
unsafe fn free(&mut self, n: *mut IndexSTSeqDllNode<K, V>) {
IndexSTSeqDllNode::dealloc_headless(n)
}
#[inline(always)]
fn alloc(&mut self, node: IndexSTSeqDllNode<K, V>, _: &mut bool) -> IndexSTSeqDllNodePtr<K, V> {
IndexSTSeqDllNode::alloc_box(node)
}
#[inline(always)]
fn cleanup(&mut self) {}
}
pub trait AllocStrategy<K, V>: Sized {
// HACK(@ohsayan): I trust the optimizer, but not so much
const METRIC_REFRESH: bool;
const NEW: Self;
fn alloc(
&mut self,
node: IndexSTSeqDllNode<K, V>,
refresh_metric: &mut bool,
) -> IndexSTSeqDllNodePtr<K, V>;
unsafe fn free(&mut self, f: *mut IndexSTSeqDllNode<K, V>);
fn cleanup(&mut self);
}
pub trait Config<K, V> {
type Hasher: AsHasher;
type AllocStrategy: AllocStrategy<K, V>;
}
pub struct ConservativeConfig<K, V>(PhantomData<super::IndexSTSeqDll<K, V, Self>>);
impl<K, V> Config<K, V> for ConservativeConfig<K, V> {
type Hasher = RandomState;
type AllocStrategy = ConservativeStrategy<K, V>;
}
pub struct LiberalConfig<K, V>(PhantomData<super::IndexSTSeqDll<K, V, Self>>);
impl<K, V> Config<K, V> for LiberalConfig<K, V> {
type Hasher = RandomState;
type AllocStrategy = LiberalStrategy<K, V>;
}

@ -24,25 +24,25 @@
* *
*/ */
pub(super) mod config;
use self::config::{AllocStrategy, Config};
use super::{AsKey, AsKeyClone, AsValue, AsValueClone, IndexBaseSpec, STIndex, STIndexSeq}; use super::{AsKey, AsKeyClone, AsValue, AsValueClone, IndexBaseSpec, STIndex, STIndexSeq};
use std::{ use std::{
alloc::{alloc as std_alloc, dealloc as std_dealloc, Layout}, alloc::{alloc as std_alloc, dealloc as std_dealloc, Layout},
borrow::Borrow, borrow::Borrow,
collections::{ collections::{
hash_map::{Iter, Keys as StdMapIterKey, RandomState, Values as StdMapIterVal}, hash_map::{Iter, Keys as StdMapIterKey, Values as StdMapIterVal},
HashMap as StdMap, HashMap as StdMap,
}, },
fmt::{self, Debug}, fmt::{self, Debug},
hash::{BuildHasher, Hash, Hasher}, hash::{Hash, Hasher},
iter::FusedIterator, iter::FusedIterator,
marker::PhantomData, marker::PhantomData,
mem, mem,
ptr::{self, NonNull}, ptr::{self, NonNull},
}; };
pub type IndexSTSeqDllDef<K, V> = IndexSTSeqDll<K, V, IndexSTSeqDllHasher>;
pub type IndexSTSeqDllHasher = RandomState;
/* /*
For the ordered index impl, we resort to some crazy unsafe code, especially because there's no other way to For the ordered index impl, we resort to some crazy unsafe code, especially because there's no other way to
deal with non-primitive Ks. That's why we'll ENTIRELY AVOID exporting any structures; if we end up using a node deal with non-primitive Ks. That's why we'll ENTIRELY AVOID exporting any structures; if we end up using a node
@ -130,7 +130,7 @@ where
} }
#[derive(Debug)] #[derive(Debug)]
struct IndexSTSeqDllNode<K, V> { pub struct IndexSTSeqDllNode<K, V> {
k: K, k: K,
v: V, v: V,
n: *mut Self, n: *mut Self,
@ -210,7 +210,7 @@ impl<K, V> IndexSTSeqDllNode<K, V> {
} }
} }
type IndexSTSeqDllNodePtr<K, V> = NonNull<IndexSTSeqDllNode<K, V>>; pub type IndexSTSeqDllNodePtr<K, V> = NonNull<IndexSTSeqDllNode<K, V>>;
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
pub struct IndexSTSeqDllMetrics { pub struct IndexSTSeqDllMetrics {
@ -219,65 +219,59 @@ pub struct IndexSTSeqDllMetrics {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
impl IndexSTSeqDllMetrics { impl IndexSTSeqDllMetrics {
pub fn raw_f(&self) -> usize { pub const fn raw_f(&self) -> usize {
self.stat_f self.stat_f
} }
fn new() -> IndexSTSeqDllMetrics { const fn new() -> IndexSTSeqDllMetrics {
Self { stat_f: 0 } Self { stat_f: 0 }
} }
} }
/// An ST-index with ordering. Inefficient ordered scanning since not in block /// An ST-index with ordering. Inefficient ordered scanning since not in block
pub struct IndexSTSeqDll<K, V, S> { pub struct IndexSTSeqDll<K, V, C: Config<K, V>> {
m: StdMap<IndexSTSeqDllKeyptr<K>, IndexSTSeqDllNodePtr<K, V>, S>, m: StdMap<IndexSTSeqDllKeyptr<K>, IndexSTSeqDllNodePtr<K, V>, C::Hasher>,
h: *mut IndexSTSeqDllNode<K, V>, h: *mut IndexSTSeqDllNode<K, V>,
f: *mut IndexSTSeqDllNode<K, V>, a: C::AllocStrategy,
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
metrics: IndexSTSeqDllMetrics, metrics: IndexSTSeqDllMetrics,
} }
impl<K, V, S: BuildHasher> IndexSTSeqDll<K, V, S> { impl<K, V, C: Config<K, V>> IndexSTSeqDll<K, V, C> {
const DEF_CAP: usize = 0; const DEF_CAP: usize = 0;
#[inline(always)] #[inline(always)]
fn _new( const fn _new(
m: StdMap<IndexSTSeqDllKeyptr<K>, IndexSTSeqDllNodePtr<K, V>, S>, m: StdMap<IndexSTSeqDllKeyptr<K>, IndexSTSeqDllNodePtr<K, V>, C::Hasher>,
h: *mut IndexSTSeqDllNode<K, V>, h: *mut IndexSTSeqDllNode<K, V>,
f: *mut IndexSTSeqDllNode<K, V>, ) -> IndexSTSeqDll<K, V, C> {
) -> IndexSTSeqDll<K, V, S> {
Self { Self {
m, m,
h, h,
f, a: C::AllocStrategy::NEW,
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
metrics: IndexSTSeqDllMetrics::new(), metrics: IndexSTSeqDllMetrics::new(),
} }
} }
#[inline(always)] #[inline(always)]
fn _new_map(m: StdMap<IndexSTSeqDllKeyptr<K>, IndexSTSeqDllNodePtr<K, V>, S>) -> Self { fn _new_map(m: StdMap<IndexSTSeqDllKeyptr<K>, IndexSTSeqDllNodePtr<K, V>, C::Hasher>) -> Self {
Self::_new(m, ptr::null_mut(), ptr::null_mut()) Self::_new(m, ptr::null_mut())
} }
#[inline(always)] #[inline(always)]
pub fn with_hasher(hasher: S) -> Self { pub fn with_hasher(hasher: C::Hasher) -> Self {
Self::with_capacity_and_hasher(Self::DEF_CAP, hasher) Self::with_capacity_and_hasher(Self::DEF_CAP, hasher)
} }
#[inline(always)] #[inline(always)]
pub fn with_capacity_and_hasher(cap: usize, hasher: S) -> Self { pub fn with_capacity_and_hasher(cap: usize, hasher: C::Hasher) -> Self {
Self::_new_map(StdMap::with_capacity_and_hasher(cap, hasher)) Self::_new_map(StdMap::with_capacity_and_hasher(cap, hasher))
} }
} fn metrics_update_f_empty(&mut self) {
#[cfg(debug_assertions)]
impl<K, V> IndexSTSeqDll<K, V, RandomState> { {
#[inline(always)] self.metrics.stat_f = 0;
pub fn new() -> Self {
Self::with_capacity(Self::DEF_CAP)
} }
#[inline(always)]
pub fn with_capacity(cap: usize) -> Self {
Self::with_capacity_and_hasher(cap, RandomState::default())
} }
} }
impl<K, V, S> IndexSTSeqDll<K, V, S> { impl<K, V, C: Config<K, V>> IndexSTSeqDll<K, V, C> {
#[inline(always)] #[inline(always)]
fn metrics_update_f_decr(&mut self) { fn metrics_update_f_decr(&mut self) {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
@ -318,35 +312,6 @@ impl<K, V, S> IndexSTSeqDll<K, V, S> {
} }
} }
#[inline(always)] #[inline(always)]
fn vacuum_free(&mut self) {
unsafe {
// UNSAFE(@ohsayan): All nullck
let mut c = self.f;
while !c.is_null() {
let nx = (*c).n;
IndexSTSeqDllNode::dealloc_headless(c);
c = nx;
self.metrics_update_f_decr();
}
}
self.f = ptr::null_mut();
}
#[inline(always)]
fn recycle_or_alloc(&mut self, node: IndexSTSeqDllNode<K, V>) -> IndexSTSeqDllNodePtr<K, V> {
if self.f.is_null() {
IndexSTSeqDllNode::alloc_box(node)
} else {
self.metrics_update_f_decr();
unsafe {
// UNSAFE(@ohsayan): Safe because we already did a nullptr check
let f = self.f;
self.f = (*self.f).n;
ptr::write(f, node);
IndexSTSeqDllNodePtr::new_unchecked(f)
}
}
}
#[inline(always)]
/// NOTE: `&mut Self` for aliasing /// NOTE: `&mut Self` for aliasing
/// ## Safety /// ## Safety
/// Ensure head is non null /// Ensure head is non null
@ -358,7 +323,7 @@ impl<K, V, S> IndexSTSeqDll<K, V, S> {
} }
} }
impl<K, V, S> IndexSTSeqDll<K, V, S> { impl<K, V, C: Config<K, V>> IndexSTSeqDll<K, V, C> {
#[inline(always)] #[inline(always)]
fn _iter_unord_kv<'a>(&'a self) -> IndexSTSeqDllIterUnordKV<'a, K, V> { fn _iter_unord_kv<'a>(&'a self) -> IndexSTSeqDllIterUnordKV<'a, K, V> {
IndexSTSeqDllIterUnordKV::new(&self.m) IndexSTSeqDllIterUnordKV::new(&self.m)
@ -391,16 +356,19 @@ impl<K, V, S> IndexSTSeqDll<K, V, S> {
} }
} }
impl<K: AsKey, V: AsValue, S: BuildHasher> IndexSTSeqDll<K, V, S> { impl<K: AsKey, V: AsValue, C: Config<K, V>> IndexSTSeqDll<K, V, C> {
#[inline(always)] #[inline(always)]
/// Clean up unused and cached memory /// Clean up unused and cached memory
fn vacuum_full(&mut self) { fn vacuum_full(&mut self) {
self.m.shrink_to_fit(); self.m.shrink_to_fit();
self.vacuum_free(); self.a.cleanup();
if C::AllocStrategy::METRIC_REFRESH {
self.metrics_update_f_empty();
}
} }
} }
impl<K: AsKey, V: AsValue, S: BuildHasher> IndexSTSeqDll<K, V, S> { impl<K: AsKey, V: AsValue, C: Config<K, V>> IndexSTSeqDll<K, V, C> {
const GET_REFRESH: bool = true; const GET_REFRESH: bool = true;
const GET_BYPASS: bool = false; const GET_BYPASS: bool = false;
#[inline(always)] #[inline(always)]
@ -474,16 +442,23 @@ impl<K: AsKey, V: AsValue, S: BuildHasher> IndexSTSeqDll<K, V, S> {
let v = ptr::read(&(*n).v); let v = ptr::read(&(*n).v);
// UNSAFE(@ohsayan): non-null guaranteed by as_ptr // UNSAFE(@ohsayan): non-null guaranteed by as_ptr
IndexSTSeqDllNode::unlink(n); IndexSTSeqDllNode::unlink(n);
(*n).n = self.f; self.a.free(n);
self.f = n; if C::AllocStrategy::METRIC_REFRESH {
self.metrics_update_f_incr(); self.metrics_update_f_incr();
}
v v
}) })
} }
#[inline(always)] #[inline(always)]
fn __insert(&mut self, k: K, v: V) -> bool { fn __insert(&mut self, k: K, v: V) -> bool {
self.ensure_sentinel(); self.ensure_sentinel();
let node = self.recycle_or_alloc(IndexSTSeqDllNode::new_null(k, v)); let mut refresh = false;
let node = self
.a
.alloc(IndexSTSeqDllNode::new_null(k, v), &mut refresh);
if C::AllocStrategy::METRIC_REFRESH & cfg!(debug_assertions) & refresh {
self.metrics_update_f_decr();
}
let kptr = unsafe { let kptr = unsafe {
// UNSAFE(@ohsayan): All g, we allocated it rn // UNSAFE(@ohsayan): All g, we allocated it rn
IndexSTSeqDllKeyptr::new(&node.as_ref().k) IndexSTSeqDllKeyptr::new(&node.as_ref().k)
@ -532,7 +507,7 @@ impl<K: AsKey, V: AsValue, S: BuildHasher> IndexSTSeqDll<K, V, S> {
} }
} }
impl<K, V, S> Drop for IndexSTSeqDll<K, V, S> { impl<K, V, C: Config<K, V>> Drop for IndexSTSeqDll<K, V, C> {
fn drop(&mut self) { fn drop(&mut self) {
if !self.h.is_null() { if !self.h.is_null() {
unsafe { unsafe {
@ -542,29 +517,27 @@ impl<K, V, S> Drop for IndexSTSeqDll<K, V, S> {
IndexSTSeqDllNode::dealloc_headless(self.h); IndexSTSeqDllNode::dealloc_headless(self.h);
} }
} }
self.vacuum_free(); self.a.cleanup();
} }
} }
impl<K: AsKey, V: AsValue, S: BuildHasher + Default> FromIterator<(K, V)> impl<K: AsKey, V: AsValue, C: Config<K, V>> FromIterator<(K, V)> for IndexSTSeqDll<K, V, C> {
for IndexSTSeqDll<K, V, S>
{
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self { fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
let mut slf = Self::with_hasher(S::default()); let mut slf = Self::with_hasher(C::Hasher::default());
iter.into_iter() iter.into_iter()
.for_each(|(k, v)| assert!(slf._insert(k, v))); .for_each(|(k, v)| assert!(slf._insert(k, v)));
slf slf
} }
} }
impl<K, V, S: BuildHasher + Default> IndexBaseSpec<K, V> for IndexSTSeqDll<K, V, S> { impl<K, V, C: Config<K, V>> IndexBaseSpec<K, V> for IndexSTSeqDll<K, V, C> {
const PREALLOC: bool = true; const PREALLOC: bool = true;
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
type Metrics = IndexSTSeqDllMetrics; type Metrics = IndexSTSeqDllMetrics;
fn idx_init() -> Self { fn idx_init() -> Self {
Self::with_hasher(S::default()) Self::with_hasher(C::Hasher::default())
} }
fn idx_init_with(s: Self) -> Self { fn idx_init_with(s: Self) -> Self {
@ -572,7 +545,7 @@ impl<K, V, S: BuildHasher + Default> IndexBaseSpec<K, V> for IndexSTSeqDll<K, V,
} }
fn idx_init_cap(cap: usize) -> Self { fn idx_init_cap(cap: usize) -> Self {
Self::with_capacity_and_hasher(cap, S::default()) Self::with_capacity_and_hasher(cap, C::Hasher::default())
} }
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
@ -581,7 +554,7 @@ impl<K, V, S: BuildHasher + Default> IndexBaseSpec<K, V> for IndexSTSeqDll<K, V,
} }
} }
impl<K, V, S: BuildHasher + Default> STIndex<K, V> for IndexSTSeqDll<K, V, S> impl<K, V, C: Config<K, V>> STIndex<K, V> for IndexSTSeqDll<K, V, C>
where where
K: AsKey, K: AsKey,
V: AsValue, V: AsValue,
@ -691,11 +664,11 @@ where
} }
} }
impl<K, V, S> STIndexSeq<K, V> for IndexSTSeqDll<K, V, S> impl<K, V, C> STIndexSeq<K, V> for IndexSTSeqDll<K, V, C>
where where
K: AsKey, K: AsKey,
V: AsValue, V: AsValue,
S: BuildHasher + Default, C: Config<K, V>,
{ {
type IterOrdKV<'a> = IndexSTSeqDllIterOrdKV<'a, K, V> type IterOrdKV<'a> = IndexSTSeqDllIterOrdKV<'a, K, V>
where where
@ -726,9 +699,9 @@ where
} }
} }
impl<K: AsKeyClone, V: AsValueClone, S: BuildHasher + Default> Clone for IndexSTSeqDll<K, V, S> { impl<K: AsKeyClone, V: AsValueClone, C: Config<K, V>> Clone for IndexSTSeqDll<K, V, C> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
let mut slf = Self::with_capacity_and_hasher(self.len(), S::default()); let mut slf = Self::with_capacity_and_hasher(self.len(), C::Hasher::default());
self._iter_ord_kv() self._iter_ord_kv()
.map(|(k, v)| (k.clone(), v.clone())) .map(|(k, v)| (k.clone(), v.clone()))
.for_each(|(k, v)| { .for_each(|(k, v)| {
@ -738,8 +711,8 @@ impl<K: AsKeyClone, V: AsValueClone, S: BuildHasher + Default> Clone for IndexST
} }
} }
unsafe impl<K: Send, V: Send, S: Send> Send for IndexSTSeqDll<K, V, S> {} unsafe impl<K: Send, V: Send, C: Config<K, V> + Send> Send for IndexSTSeqDll<K, V, C> {}
unsafe impl<K: Sync, V: Sync, S: Sync> Sync for IndexSTSeqDll<K, V, S> {} unsafe impl<K: Sync, V: Sync, C: Config<K, V> + Sync> Sync for IndexSTSeqDll<K, V, C> {}
macro_rules! unsafe_marker_impl { macro_rules! unsafe_marker_impl {
(unsafe impl for $ty:ty) => { (unsafe impl for $ty:ty) => {
@ -967,7 +940,7 @@ struct IndexSTSeqDllIterOrdBase<'a, K: 'a, V: 'a, C: IndexSTSeqDllIterOrdConfig<
impl<'a, K: 'a, V: 'a, C: IndexSTSeqDllIterOrdConfig<K, V>> IndexSTSeqDllIterOrdBase<'a, K, V, C> { impl<'a, K: 'a, V: 'a, C: IndexSTSeqDllIterOrdConfig<K, V>> IndexSTSeqDllIterOrdBase<'a, K, V, C> {
#[inline(always)] #[inline(always)]
fn new<S>(idx: &'a IndexSTSeqDll<K, V, S>) -> Self { fn new<Mc: Config<K, V>>(idx: &'a IndexSTSeqDll<K, V, Mc>) -> Self {
Self { Self {
h: if idx.h.is_null() { h: if idx.h.is_null() {
ptr::null_mut() ptr::null_mut()

@ -27,16 +27,23 @@
use super::*; use super::*;
mod idx_st_seq_dll { mod idx_st_seq_dll {
use super::{stord::IndexSTSeqDllDef, IndexBaseSpec, STIndex, STIndexSeq}; use super::{IndexBaseSpec, IndexSTSeqLib, STIndex, STIndexSeq};
use rand::{distributions::Alphanumeric, Rng}; use rand::{distributions::Alphanumeric, Rng};
#[cfg(not(miri))]
const SPAM_CNT: usize = 131_072; const SPAM_CNT: usize = 131_072;
#[cfg(miri)]
const SPAM_CNT: usize = 128;
#[cfg(not(miri))]
const SPAM_SIZE: usize = 128; const SPAM_SIZE: usize = 128;
type Index = IndexSTSeqDllDef<String, String>; #[cfg(miri)]
const SPAM_SIZE: usize = 4;
type Index = IndexSTSeqLib<String, String>;
/// Returns an index with: `i -> "{i+1}"` starting from 0 upto the value of [`SPAM_CNT`] /// Returns an index with: `i -> "{i+1}"` starting from 0 upto the value of [`SPAM_CNT`]
fn mkidx() -> IndexSTSeqDllDef<usize, String> { fn mkidx() -> IndexSTSeqLib<usize, String> {
let mut idx = IndexSTSeqDllDef::idx_init(); let mut idx = IndexSTSeqLib::idx_init();
for int in 0..SPAM_CNT { for int in 0..SPAM_CNT {
assert!(idx.st_insert(int, (int + 1).to_string())); assert!(idx.st_insert(int, (int + 1).to_string()));
} }
@ -66,7 +73,7 @@ mod idx_st_seq_dll {
} }
#[test] #[test]
fn spam_read_nx() { fn spam_read_nx() {
let idx = IndexSTSeqDllDef::<usize, String>::new(); let idx = IndexSTSeqLib::<usize, String>::idx_init();
for int in SPAM_CNT..SPAM_CNT * 2 { for int in SPAM_CNT..SPAM_CNT * 2 {
assert!(idx.st_get(&int).is_none()); assert!(idx.st_get(&int).is_none());
} }
@ -80,14 +87,14 @@ mod idx_st_seq_dll {
} }
#[test] #[test]
fn spam_update_nx() { fn spam_update_nx() {
let mut idx = IndexSTSeqDllDef::<usize, String>::new(); let mut idx = IndexSTSeqLib::<usize, String>::idx_init();
for int in 0..SPAM_CNT { for int in 0..SPAM_CNT {
assert!(!idx.st_update(&int, (int + 2).to_string())); assert!(!idx.st_update(&int, (int + 2).to_string()));
} }
} }
#[test] #[test]
fn spam_delete_nx() { fn spam_delete_nx() {
let mut idx = IndexSTSeqDllDef::<usize, String>::new(); let mut idx = IndexSTSeqLib::<usize, String>::idx_init();
for int in 0..SPAM_CNT { for int in 0..SPAM_CNT {
assert!(!idx.st_delete(&int)); assert!(!idx.st_delete(&int));
} }
@ -104,7 +111,7 @@ mod idx_st_seq_dll {
} }
#[test] #[test]
fn spam_crud() { fn spam_crud() {
let mut idx = IndexSTSeqDllDef::idx_init(); let mut idx = IndexSTSeqLib::idx_init();
for int in 0..SPAM_CNT { for int in 0..SPAM_CNT {
assert!(idx.st_insert(int, int + 1)); assert!(idx.st_insert(int, int + 1));
assert_eq!(*idx.st_get(&int).unwrap(), int + 1); assert_eq!(*idx.st_get(&int).unwrap(), int + 1);
@ -116,7 +123,7 @@ mod idx_st_seq_dll {
} }
#[test] #[test]
fn spam_read() { fn spam_read() {
let mut idx = IndexSTSeqDllDef::idx_init(); let mut idx = IndexSTSeqLib::idx_init();
for int in 0..SPAM_CNT { for int in 0..SPAM_CNT {
let v = (int + 1).to_string(); let v = (int + 1).to_string();
assert!(idx.st_insert(int, v.clone())); assert!(idx.st_insert(int, v.clone()));

Loading…
Cancel
Save