diff --git a/worldsim/src/lodstore/data.rs b/worldsim/src/lodstore/data.rs index 44199d7434..4fa4d5f3f2 100644 --- a/worldsim/src/lodstore/data.rs +++ b/worldsim/src/lodstore/data.rs @@ -52,12 +52,23 @@ pub struct HashIter<'a, C: DetailStore> { pub( super ) wanted: LodPos, pub( super ) layer_lod: LodPos, //LodPos aligned to layer::LEVEL } +pub struct HashIterMut<'a, C: DetailStore> { + pub( super ) layer: &'a mut C, + pub( super ) wanted: LodPos, + pub( super ) layer_lod: LodPos, //LodPos aligned to layer::LEVEL +} pub struct VecIter<'a, C: DetailStore> { pub( super ) layer: &'a C, pub( super ) wanted: LodPos, pub( super ) layer_lod: LodPos, //LodPos aligned to layer::LEVEL pub( super ) layer_key: usize, } +pub struct VecIterMut<'a, C: DetailStore> { + pub( super ) layer: &'a mut C, + pub( super ) wanted: LodPos, + pub( super ) layer_lod: LodPos, //LodPos aligned to layer::LEVEL + pub( super ) layer_key: usize, +} impl IndexStore for VecNestLayer { type INDEX = I; @@ -136,6 +147,7 @@ pub mod tests { use crate::lodstore::data::*; use test::Bencher; use std::{u16, u32}; + use crate::lodstore::traversable::Traversable; #[rustfmt::skip] pub type ExampleData = @@ -240,6 +252,36 @@ pub mod tests { assert_eq!(*x.trav(LodPos::xyz(0, 2, 0)).get().get().get().mat(), 0_i8); } + #[test] + fn mut_simple_elements() { + let mut x = gen_simple_example(); + assert_eq!(*x.trav(LodPos::xyz(0, 0, 0)).get().get().get().mat(), 7_i8); + assert_eq!(*x.trav(LodPos::xyz(0, 0, 1)).get().get().get().mat(), 6_i8); + x.trav_mut(LodPos::xyz(0, 0, 0)).get().get().get().store(123); + assert_eq!(*x.trav(LodPos::xyz(0, 0, 0)).get().get().get().mat(), 123_i8); + } + + #[test] + fn mut2_simple_elements() { + let mut x = gen_simple_example(); + assert_eq!(*x.trav(LodPos::xyz(0, 0, 0)).get().get().get().mat(), 7_i8); + let c = *x.trav(LodPos::xyz(0, 0, 0)).get().get().get().mat(); + x.trav_mut(LodPos::xyz(0, 0, 0)).get().get().get().store(111 + c); + assert_eq!(*x.trav(LodPos::xyz(0, 0, 0)).get().get().get().mat(), 118_i8); + } + + /* allow this once we guarante get to be consistent even on Hash Lookups! + TODO: shuldnt this already ne the case ? + #[test] + fn mut3_simple_elements() { + let mut x = gen_simple_example(); + let a = x.trav_mut(LodPos::xyz(0, 0, 0)).get().get().get(); + assert_eq!(*a.mat(), 7_i8); + a.store(123); + assert_eq!(*a.mat(), 123_i8); + assert_eq!(*x.trav(LodPos::xyz(0, 0, 0)).get().get().get().mat(), 123_i8); + }*/ + #[bench] fn bench_access_trav(b: &mut Bencher) { let x = gen_simple_example(); diff --git a/worldsim/src/lodstore/entrylayer.rs b/worldsim/src/lodstore/entrylayer.rs index 1bf7f77bf6..fec353327b 100644 --- a/worldsim/src/lodstore/entrylayer.rs +++ b/worldsim/src/lodstore/entrylayer.rs @@ -1,13 +1,15 @@ use super::index::ToOptionUsize; use super::lodpos::LodPos; -use super::data::{HashNestLayer, DetailStore, HashIter}; +use super::data::{HashNestLayer, DetailStore, HashIter, HashIterMut}; use super::delta::{VecNestDelta, Delta, VecDataIter, DataWriterIter, DeltaWriter}; use super::traversable::Traversable; use std::marker::PhantomData; pub trait EntryLayer<'a> { type TRAV: Traversable; + type TRAV_MUT: Traversable; fn trav(&'a self, pos: LodPos) -> Self::TRAV; + fn trav_mut(&'a mut self, pos: LodPos) -> Self::TRAV_MUT; } ///////////////// data types @@ -16,10 +18,20 @@ impl<'a, C: 'a + DetailStore, T: 'a, I: 'a + ToOptionUsize, const L: u8> EntryLa for HashNestLayer { type TRAV = HashIter<'a, HashNestLayer>; + type TRAV_MUT = HashIterMut<'a, HashNestLayer>; + //ERROR make the HashIter C: remove the &'a from HashIter coding and implement it here fn trav(&'a self, pos: LodPos) -> Self::TRAV { HashIter { - layer: &self, + layer: self, + wanted: pos, + layer_lod: pos.align_to_level({ L }), + } + } + + fn trav_mut(&'a mut self, pos: LodPos) -> Self::TRAV_MUT { + HashIterMut { + layer: self, wanted: pos, layer_lod: pos.align_to_level({ L }), } @@ -30,9 +42,13 @@ for HashNestLayer impl<'a, D: 'a + Delta, T: 'a, const L: u8> EntryLayer<'a> for VecNestDelta { type TRAV = VecDataIter<'a, VecNestDelta>; + type TRAV_MUT = VecDataIter<'a, VecNestDelta>; fn trav(&'a self, _pos: LodPos) -> Self::TRAV { - VecDataIter { layer: &self } + VecDataIter { layer: self } + } + fn trav_mut(&'a mut self, _pos: LodPos) -> Self::TRAV_MUT { + VecDataIter { layer: self } } } @@ -43,6 +59,8 @@ for DeltaWriter<'a, C, D> <>::TRAV as Traversable>::TRAV_CHILD: Traversable, { type TRAV = DataWriterIter<'a, D::TRAV, C::TRAV>; + type TRAV_MUT = DataWriterIter<'a, D::TRAV, C::TRAV>; + fn trav(&'a self, pos: LodPos) -> DataWriterIter { DataWriterIter { delta_iter: self.delta.trav(pos), @@ -50,4 +68,12 @@ for DeltaWriter<'a, C, D> _a: PhantomData::<&'a ()>::default(), } } + + fn trav_mut(&'a mut self, pos: LodPos) -> DataWriterIter { + DataWriterIter { + delta_iter: self.delta.trav(pos), + data_iter: self.data.trav(pos), + _a: PhantomData::<&'a ()>::default(), + } + } } \ No newline at end of file diff --git a/worldsim/src/lodstore/layer.rs b/worldsim/src/lodstore/layer.rs index d1035f95b1..48d0de4f57 100644 --- a/worldsim/src/lodstore/layer.rs +++ b/worldsim/src/lodstore/layer.rs @@ -12,6 +12,7 @@ pub trait Layer { pub trait ParentLayer: Layer { type CHILD: Layer; fn child(&self) -> &Self::CHILD; + fn child_mut(&mut self) -> &mut Self::CHILD; const CHILDS_PER_OWN_TOTAL: usize = two_pow_u(Self::LOG2_OF_CHILDS_PER_OWN_TOTAL) as usize; const LOG2_OF_CHILDS_PER_OWN_TOTAL: u8 = 3 * ({ Self::LEVEL } - Self::CHILD::LEVEL); const CHILDS_PER_OWN: Vec3 = Vec3 { @@ -47,6 +48,9 @@ impl ParentLayer fn child(&self) -> &Self::CHILD { &self.child } + fn child_mut(&mut self) -> &mut Self::CHILD { + &mut self.child + } } impl ParentLayer for HashNestLayer @@ -55,6 +59,9 @@ impl ParentLayer fn child(&self) -> &Self::CHILD { &self.child } + fn child_mut(&mut self) -> &mut Self::CHILD { + &mut self.child + } } ///////////////// delta types @@ -73,4 +80,7 @@ impl ParentLayer for VecNestDelta { fn child(&self) -> &Self::CHILD { &self.child } + fn child_mut(&mut self) -> &mut Self::CHILD { + &mut self.child + } } \ No newline at end of file diff --git a/worldsim/src/lodstore/materializeable.rs b/worldsim/src/lodstore/materializeable.rs index fad466d7e6..c3faf6b786 100644 --- a/worldsim/src/lodstore/materializeable.rs +++ b/worldsim/src/lodstore/materializeable.rs @@ -1,36 +1,80 @@ use super::lodpos::{LodPos}; -use super::data::{DetailStore, HashIter, VecIter}; +use super::data::{DetailStore, HashIter, VecIter, HashIterMut, VecIterMut}; use super::delta::DataWriterIter; -pub trait Materializeable { +/* + +TODO: how do we want traversable and meterializeable to work? +I e.g. should +let value = lodtree,trav().get().get().mat(); +be possibe? should it create a read lock on lodtree? + +ideally: +let mut v = lodtree.trav().get().get().get().mutmat() +has a read lock on lottree and a writelock on that specific field, but that wont stop us from taking another get.get.get on lodtree on the same item. mhhh arrgg, this is dificult to do statically. so better not do it ? + + +VLT multiple types ? for efficient returns? + +*/ + +pub trait Materializeable<'a> { type MAT_CHILD; - fn mat(self) -> Self::MAT_CHILD; + fn mat(self) -> &'a Self::MAT_CHILD; + fn store(self, mat: Self::MAT_CHILD); } ///////////////// data types -impl<'a, L: DetailStore> Materializeable for HashIter<'a, L> { - type MAT_CHILD = &'a L::DETAIL; +impl<'a, L: DetailStore> Materializeable<'a> for HashIter<'a, L> { +type MAT_CHILD = L::DETAIL; + +fn mat(self) -> &'a L::DETAIL { +DetailStore::load(self.layer, self.layer_lod) +} +fn store(self, mat: L::DETAIL) { +//DetailStore::save(self.layer, self.layer_key, mat) +} +} + +impl<'a, L: DetailStore> Materializeable<'a> for HashIterMut<'a, L> { + type MAT_CHILD = L::DETAIL; fn mat(self) -> &'a L::DETAIL { DetailStore::load(self.layer, self.layer_lod) } + fn store(self, mat: L::DETAIL) { +//DetailStore::save(self.layer, self.layer_key, mat) + } } -impl<'a, L: DetailStore> Materializeable for VecIter<'a, L> { - type MAT_CHILD = &'a L::DETAIL; +impl<'a, L: DetailStore> Materializeable<'a> for VecIter<'a, L> { +type MAT_CHILD = L::DETAIL; - fn mat(self) -> &'a L::DETAIL { - DetailStore::load(self.layer, self.layer_key) +fn mat(self) -> &'a L::DETAIL { DetailStore::load(self.layer, self.layer_key) } +fn store(self, mat: L::DETAIL) { +//DetailStore::save(self.layer, self.layer_key, mat) +} +} + +impl<'a, L: DetailStore> Materializeable<'a> for VecIterMut<'a, L> { + type MAT_CHILD = L::DETAIL; + + fn mat(self) -> &'a L::DETAIL { DetailStore::load(self.layer, self.layer_key) } + fn store(self, mat: L::DETAIL) { + DetailStore::save(self.layer, self.layer_key, mat) } } ///////////////// delta types -impl<'a, DT, CT: Materializeable> Materializeable for DataWriterIter<'a, DT, CT> { - type MAT_CHILD = CT::MAT_CHILD; +impl<'a, DT, CT: Materializeable<'a>> Materializeable<'a> for DataWriterIter<'a, DT, CT> { +type MAT_CHILD = CT::MAT_CHILD; - fn mat(self) -> CT::MAT_CHILD { - self.data_iter.mat() - } +fn mat(self) -> &'a CT::MAT_CHILD { +self.data_iter.mat() +} +fn store(self, mat: CT::MAT_CHILD) { +//self.data_iter.store(mat) +} } diff --git a/worldsim/src/lodstore/traversable.rs b/worldsim/src/lodstore/traversable.rs index 54d3743d01..a9dcf6c982 100644 --- a/worldsim/src/lodstore/traversable.rs +++ b/worldsim/src/lodstore/traversable.rs @@ -1,6 +1,6 @@ use super::index::ToOptionUsize; use super::lodpos::{multily_with_2_pow_n, relative_to_1d, LodPos}; -use super::data::{DetailStore, IndexStore, HashIter, VecIter}; +use super::data::{DetailStore, IndexStore, HashIter, VecIter, HashIterMut, VecIterMut}; use super::delta::{Delta, VecDataIter, DataWriterIter}; #[allow(unused_imports)] //not unsued, cargo is just to stupud to detect that use super::layer::{Layer, ParentLayer}; @@ -40,6 +40,33 @@ impl<'a, L: DetailStore + IndexStore> Traversable for HashIter<'a, } } +impl<'a, L: DetailStore + IndexStore> Traversable for HashIterMut<'a, L> + where + L::CHILD: DetailStore, +{ + type TRAV_CHILD = VecIterMut<'a, L::CHILD>; + + fn get(self) -> VecIterMut<'a, L::CHILD> { + let child_lod = self.wanted.align_to_level(L::CHILD::LEVEL); + let pos_offset = relative_to_1d( + child_lod, + self.layer_lod, + L::CHILD::LEVEL, + L::CHILDS_PER_OWN, + ); + let layer_key = (multily_with_2_pow_n( + IndexStore::load(self.layer, self.layer_lod).into_usize(), + L::LOG2_OF_CHILDS_PER_OWN_TOTAL, + )) + pos_offset; + VecIterMut { + layer: self.layer.child_mut(), + wanted: self.wanted, + layer_key, + layer_lod: child_lod, + } + } +} + impl<'a, L: DetailStore + IndexStore> Traversable for VecIter<'a, L> where L::CHILD: DetailStore, @@ -67,6 +94,33 @@ impl<'a, L: DetailStore + IndexStore> Traversable for VecIter<'a, L } } +impl<'a, L: DetailStore + IndexStore> Traversable for VecIterMut<'a, L> + where + L::CHILD: DetailStore, +{ + type TRAV_CHILD = VecIterMut<'a, L::CHILD>; + + fn get(self) -> VecIterMut<'a, L::CHILD> { + let child_lod = self.wanted.align_to_level(L::CHILD::LEVEL); + let pos_offset = relative_to_1d( + child_lod, + self.layer_lod, + L::CHILD::LEVEL, + L::CHILDS_PER_OWN, + ); + let layer_key = (multily_with_2_pow_n( + IndexStore::load(self.layer, self.layer_key).into_usize(), + L::LOG2_OF_CHILDS_PER_OWN_TOTAL, + )) + pos_offset; + VecIterMut { + layer: self.layer.child_mut(), + wanted: self.wanted, + layer_key, + layer_lod: child_lod, + } + } +} + ///////////////// delta types impl<'a, D: Delta + ParentLayer> Traversable for VecDataIter<'a, D>