Skip to content

Commit

Permalink
Merge pull request #1121 from hannobraun/store
Browse files Browse the repository at this point in the history
Expand store API
  • Loading branch information
hannobraun authored Sep 20, 2022
2 parents 60fd0ac + 3468282 commit 92e0829
Show file tree
Hide file tree
Showing 5 changed files with 387 additions and 293 deletions.
20 changes: 11 additions & 9 deletions crates/fj-kernel/src/algorithms/approx/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::collections::BTreeMap;
use crate::{
objects::{Curve, GlobalCurve},
path::{GlobalPath, SurfacePath},
stores::Handle,
stores::{Handle, ObjectId},
};

use super::{path::RangeOnPath, Approx, ApproxPoint, Tolerance};
Expand All @@ -30,12 +30,12 @@ impl Approx for (&Curve, RangeOnPath) {
) -> Self::Approximation {
let (curve, range) = self;

let cache_key = (curve.global_form().clone(), range);
let global_curve_approx = match cache.get(cache_key.clone()) {
let global_curve = curve.global_form().clone();
let global_curve_approx = match cache.get(global_curve.clone(), range) {
Some(approx) => approx,
None => {
let approx = approx_global_curve(curve, range, tolerance);
cache.insert(cache_key, approx)
cache.insert(global_curve, range, approx)
}
};

Expand Down Expand Up @@ -152,7 +152,7 @@ impl CurveApprox {
/// A cache for results of an approximation
#[derive(Default)]
pub struct CurveCache {
inner: BTreeMap<(Handle<GlobalCurve>, RangeOnPath), GlobalCurveApprox>,
inner: BTreeMap<(ObjectId, RangeOnPath), GlobalCurveApprox>,
}

impl CurveCache {
Expand All @@ -164,19 +164,21 @@ impl CurveCache {
/// Insert the approximation of a [`GlobalCurve`]
pub fn insert(
&mut self,
key: (Handle<GlobalCurve>, RangeOnPath),
handle: Handle<GlobalCurve>,
range: RangeOnPath,
approx: GlobalCurveApprox,
) -> GlobalCurveApprox {
self.inner.insert(key, approx.clone());
self.inner.insert((handle.id(), range), approx.clone());
approx
}

/// Access the approximation for the given [`GlobalCurve`], if available
pub fn get(
&self,
key: (Handle<GlobalCurve>, RangeOnPath),
handle: Handle<GlobalCurve>,
range: RangeOnPath,
) -> Option<GlobalCurveApprox> {
self.inner.get(&key).cloned()
self.inner.get(&(handle.id(), range)).cloned()
}
}

Expand Down
137 changes: 137 additions & 0 deletions crates/fj-kernel/src/stores/blocks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use std::iter;

#[derive(Debug)]
pub struct Blocks<T> {
inner: Vec<Block<T>>,
block_size: usize,
}

impl<T> Blocks<T> {
pub fn new(block_size: usize) -> Self {
Self {
inner: Vec::new(),
block_size,
}
}

pub fn push(&mut self, object: T) -> *const Option<T> {
let (index, _) = self.reserve();
self.insert(index, object)
}

pub fn reserve(&mut self) -> ((usize, usize), *mut Option<T>) {
let mut current_block = match self.inner.pop() {
Some(block) => block,
None => Block::new(self.block_size),
};

let ret = loop {
match current_block.reserve() {
Ok((object_index, ptr)) => {
let block_index = self.inner.len();
break ((block_index, object_index), ptr);
}
Err(()) => {
// Block is full. Need to create a new one and retry.
self.inner.push(current_block);
current_block = Block::new(self.block_size);
}
}
};

self.inner.push(current_block);

ret
}

pub fn insert(
&mut self,
(block_index, object_index): (usize, usize),
object: T,
) -> *const Option<T> {
let block = &mut self.inner[block_index];
block.insert(object_index, object)
}

pub fn get(&self, index: usize) -> Option<&Block<T>> {
self.inner.get(index)
}

#[cfg(test)]
pub fn iter(&self) -> impl Iterator<Item = &T> + '_ {
self.inner.iter().flat_map(|block| block.iter())
}
}

#[derive(Debug)]
pub struct Block<T> {
objects: Box<[Option<T>]>,
next: usize,
}

impl<T> Block<T> {
pub fn new(size: usize) -> Self {
let vec = iter::repeat_with(|| None)
.take(size)
.collect::<Vec<Option<T>>>();
let objects = vec.into_boxed_slice();

Self { objects, next: 0 }
}

pub fn reserve(&mut self) -> Result<(usize, *mut Option<T>), ()> {
if self.next >= self.objects.len() {
return Err(());
}

let index = self.next;
let ptr = &mut self.objects[self.next];
self.next += 1;

Ok((index, ptr))
}

pub fn insert(&mut self, index: usize, object: T) -> *const Option<T> {
self.objects[index] = Some(object);
&self.objects[index]
}

pub fn get(&self, index: usize) -> &Option<T> {
&self.objects[index]
}

pub fn len(&self) -> usize {
self.next
}

#[cfg(test)]
pub fn iter(&self) -> impl Iterator<Item = &T> + '_ {
let mut i = 0;
iter::from_fn(move || {
if i >= self.len() {
return None;
}

let object = self.get(i).as_ref()?;
i += 1;

Some(object)
})
}
}

#[cfg(test)]
mod tests {
use super::Blocks;

#[test]
fn push() {
let mut blocks = Blocks::new(1);

blocks.push(0);
blocks.push(1);

let objects = blocks.iter().copied().collect::<Vec<_>>();
assert_eq!(objects, [0, 1]);
}
}
Loading

0 comments on commit 92e0829

Please sign in to comment.