just cache the index

This commit is contained in:
Niko Matsakis 2024-07-28 11:29:26 +00:00
parent 9f95b37af9
commit bca9180e05

View file

@ -1,4 +1,5 @@
use std::any::{Any, TypeId}; use std::any::{Any, TypeId};
use std::marker::PhantomData;
use std::thread::ThreadId; use std::thread::ThreadId;
use orx_concurrent_vec::ConcurrentVec; use orx_concurrent_vec::ConcurrentVec;
@ -242,7 +243,8 @@ pub struct IngredientCache<I>
where where
I: Ingredient, I: Ingredient,
{ {
cached_data: std::sync::OnceLock<(Nonce<StorageNonce>, *const I)>, cached_data: std::sync::OnceLock<(Nonce<StorageNonce>, IngredientIndex)>,
phantom: PhantomData<fn() -> I>,
} }
unsafe impl<I> Sync for IngredientCache<I> where I: Ingredient + Sync {} unsafe impl<I> Sync for IngredientCache<I> where I: Ingredient + Sync {}
@ -264,6 +266,7 @@ where
pub const fn new() -> Self { pub const fn new() -> Self {
Self { Self {
cached_data: std::sync::OnceLock::new(), cached_data: std::sync::OnceLock::new(),
phantom: PhantomData,
} }
} }
@ -274,24 +277,24 @@ where
db: &'s dyn Database, db: &'s dyn Database,
create_index: impl Fn() -> IngredientIndex, create_index: impl Fn() -> IngredientIndex,
) -> &'s I { ) -> &'s I {
let &(nonce, ingredient) = self.cached_data.get_or_init(|| { let zalsa = db.zalsa();
let ingredient = self.create_ingredient(db, &create_index); let (nonce, index) = self.cached_data.get_or_init(|| {
(db.zalsa().nonce(), ingredient as *const I) let index = create_index();
(zalsa.nonce(), index)
}); });
if db.zalsa().nonce() == nonce { // FIXME: We used to cache a raw pointer to the revision but miri
unsafe { &*ingredient } // was reporting errors because that pointer was derived from an `&`
} else { // that is invalidated when the next revision starts with an `&mut`.
self.create_ingredient(db, &create_index) //
} // We could fix it with orxfun/orx-concurrent-vec#18 or by "refreshing" the cache
} // when the revision changes but just caching the index is an awful lot simpler.
fn create_ingredient<'s>( if db.zalsa().nonce() == *nonce {
&self, zalsa.lookup_ingredient(*index).assert_type::<I>()
storage: &'s dyn Database, } else {
create_index: &impl Fn() -> IngredientIndex,
) -> &'s I {
let index = create_index(); let index = create_index();
storage.zalsa().lookup_ingredient(index).assert_type::<I>() zalsa.lookup_ingredient(index).assert_type::<I>()
}
} }
} }