From 3b12190fc6ddc687bedee0d2d01475bbe279804f Mon Sep 17 00:00:00 2001 From: paladin Date: Mon, 28 Sep 2026 11:57:44 +0100 Subject: [PATCH] Refactoring for new types Map and Set, renaming of DisplacementSet and its methods. Builds, not tested. --- src/gc.rs | 4 ++ src/lib.rs | 10 +++- src/map.rs | 171 ++++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 144 insertions(+), 41 deletions(-) diff --git a/src/gc.rs b/src/gc.rs index 12e66a7..73b3068 100644 --- a/src/gc.rs +++ b/src/gc.rs @@ -197,6 +197,10 @@ impl Traverse for IdNode where C: Allocates { IdNode::traverse(next,context) } } + + fn collect(self) { + todo!() + } } #[derive(Clone)] diff --git a/src/lib.rs b/src/lib.rs index 938c419..c830934 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,10 @@ pub mod gc; -pub mod map; \ No newline at end of file +pub mod map; + +#[cfg(test)] +mod tests { + #[test] + fn simple() { + + } +} \ No newline at end of file diff --git a/src/map.rs b/src/map.rs index 5aae0ab..a71e422 100644 --- a/src/map.rs +++ b/src/map.rs @@ -70,70 +70,71 @@ impl Hashes for AnyId { } pub trait TableEntry: Equivalent + Hashes { - fn new_vacant() -> Self; + const VACANT: Self; fn is_vacant(&self) -> bool; } -#[derive(Debug, Clone)] -pub struct Entry { +#[derive(Debug)] +pub struct Entry { pub entry: E, home: usize, displacement: Displacement, } -#[derive(Clone, Debug)] -pub struct Map { +impl Entry { + const VACANT: Entry = Entry { + entry: E::VACANT, + home: 0, + displacement: 0, + }; +} + +#[derive(Debug)] +pub struct DisplacementSet { // default representing vacancy! pub map: Vec>, // todo: make this private and use an iterator map_bounds: std::ops::Range, map_count: usize, // number of elements in table } -impl Map { - fn exchange_table(&mut self, len: usize) { +impl DisplacementSet { + fn exchange(&mut self, len: usize) { let old = std::mem::replace( &mut self.map, - vec![ - Entry { - entry: E::new_vacant(), - home: 0, - displacement: 0, - }; - len - ], + (0..len).map(|_| Entry::VACANT).collect() // todo: I don't like that this may go over all memory ); - self.map_bounds = self.table_lower()..self.table_upper(); + self.map_bounds = self.lower()..self.upper(); for Entry { entry, .. } in old { if !entry.is_vacant() { - self.set_table(entry) + self.set(entry) } } } - pub fn resize_table(&mut self, len: usize) { - self.exchange_table(len.max(self.map_count + (self.map_count / 3))); - self.map_bounds = 0..self.table_upper(); + pub fn resize(&mut self, len: usize) { + self.exchange(len.max(self.map_count + (self.map_count / 3))); + self.map_bounds = 0..self.upper(); } - fn table_upper(&self) -> usize { + fn upper(&self) -> usize { (self.map.len() / 4) * 3 } - fn table_lower(&self) -> usize { + fn lower(&self) -> usize { self.map.len() / 3 } - fn ensure_table(&mut self) { - if self.map_count + 1 > self.table_upper() { + fn ensure(&mut self) { + if self.map_count + 1 > self.upper() { // free space is short - self.exchange_table((self.map.len() + 4) * 2); - } else if self.map_count < self.table_lower() { + self.exchange((self.map.len() + 4) * 2); + } else if self.map_count < self.lower() { // too much free space - self.exchange_table(self.map.len() / 2) + self.exchange(self.map.len() / 2) } } - pub fn set_table(&mut self, entry: E) { + pub fn set(&mut self, entry: E) { #[cfg(feature = "assertions")] assert!(!entry.is_vacant()); if !self.map_bounds.contains(&(self.map_count + 1)) { // make sure the table is appropriately sized - self.ensure_table(); + self.ensure(); } let range = self.map.len(); let home = entry.hashed() as usize % range; @@ -197,11 +198,11 @@ impl Map { // must resize #[cfg(feature = "messages")] eprintln!("\n\tResizing..."); - self.resize_table((self.map.len() + 4) * 2); - self.set_table(entry); + self.resize((self.map.len() + 4) * 2); + self.set(entry); } } - pub fn rem_table(&mut self, index: K) + pub fn remove(&mut self, index: K) where E: Equivalent, K: Hashes, @@ -212,7 +213,7 @@ impl Map { let range = self.map.len(); let home = index.hashed() as usize % range; if self.map[home].entry.matches(&index) { - self.map[home].entry = E::new_vacant(); + self.map[home].entry = E::VACANT; self.map_count -= 1; } else { if self.map[home].displacement != Displacement::MAX { @@ -220,7 +221,7 @@ impl Map { for i in 1..self.map[home].displacement { let neighbour = &mut self.map[(home + i as usize) % range]; // todo: maybe mod slows this down if neighbour.entry.matches(&index) { - neighbour.entry = E::new_vacant(); + neighbour.entry = E::VACANT; self.map_count -= 1; if i == self.map[home].displacement { self.map[home].displacement = largest @@ -237,7 +238,7 @@ impl Map { for k in 0..self.map.len() { let neighbour = &mut self.map[k]; if neighbour.entry.matches(&index) { - neighbour.entry = E::new_vacant(); + neighbour.entry = E::VACANT; self.map_count -= 1; #[cfg(feature = "assertions")] { @@ -261,7 +262,7 @@ impl Map { } } } - pub fn get_table(&mut self, index: K) -> Option<&E> + pub fn get(&mut self, index: K) -> Option<&E> where E: Equivalent, K: Hashes, @@ -283,8 +284,8 @@ impl Map { None } } - pub fn new() -> Map { - Map { + pub fn new() -> DisplacementSet { + DisplacementSet { map: Vec::new(), map_count: 0, map_bounds: (0..0).into(), @@ -292,6 +293,96 @@ impl Map { } } -pub struct TableEntry +#[derive(Clone)] +pub struct MapEntry(Option<(K,V)>); -pub type Table = Map<> \ No newline at end of file +impl Equivalent for MapEntry { + fn matches(&self, other: &K) -> bool { + &self.0.as_ref().unwrap().0 == other + } +} + +impl Hashes for MapEntry { + fn hashed(&self) -> Hashed { + self.0.as_ref().unwrap().0.hashed() + } +} + +impl PartialEq for MapEntry { + fn eq(&self, other: &Self) -> bool { + self.0.as_ref().unwrap().0 == other.0.as_ref().unwrap().0 + } +} + +impl TableEntry for MapEntry { + const VACANT: Self = MapEntry(None); + fn is_vacant(&self) -> bool { + self.0.is_none() + } +} + +pub struct Map(DisplacementSet>); + +impl Map { + pub fn resize(&mut self, len: usize) { + self.0.resize(len) + } + pub fn set(&mut self, index: K, value: V) { + self.0.set(MapEntry(Some((index,value)))); + } + pub fn remove(&mut self, index: K) { + self.0.remove(index); + } + pub fn get(&mut self, index: K) -> Option<&V> { + if let Some(ref entry) = self.0.get(index) { + Some(&entry.0.as_ref().unwrap().1) + } else { None } + } + pub fn new() -> Map { + Map(DisplacementSet::new()) + } +} + +#[derive(PartialEq)] +pub struct SetEntry(Option); + +pub struct Set(DisplacementSet>); + +impl Hashes for SetEntry { + fn hashed(&self) -> Hashed { + todo!() + } +} + +impl TableEntry for SetEntry { + const VACANT: Self = SetEntry(None); + fn is_vacant(&self) -> bool { + self.0.is_none() + } +} + +impl Equivalent for SetEntry { + fn matches(&self, other: &E) -> bool { + self.0.as_ref().unwrap() == other + } +} + +impl Set { + pub fn resize(&mut self, len: usize) { + self.0.resize(len) + } + pub fn set(&mut self, element: E) { + self.0.set(SetEntry(Some(element))); + } + pub fn remove(&mut self, element: E) { + self.0.remove(element); + } + pub fn get(&mut self, element: E) -> Option<&E> { + if let Some(ref entry) = self.0.get(element) { + Some(&entry.0.as_ref().unwrap()) + } else { None } + } + pub fn new() -> Set { + Set(DisplacementSet::new()) + } +} \ No newline at end of file