diff --git a/components/salsa-2022/src/alloc.rs b/components/salsa-2022/src/alloc.rs new file mode 100644 index 00000000..633b52a7 --- /dev/null +++ b/components/salsa-2022/src/alloc.rs @@ -0,0 +1,42 @@ +use std::ptr::NonNull; + +/// A box but without the uniqueness guarantees. +pub struct Alloc { + data: NonNull, +} + +impl Alloc { + pub fn new(data: T) -> Self { + let data = Box::new(data); + let data = Box::into_raw(data); + Alloc { + data: unsafe { NonNull::new_unchecked(data) }, + } + } +} + +impl Drop for Alloc { + fn drop(&mut self) { + let data: *mut T = self.data.as_ptr(); + let data: Box = unsafe { Box::from_raw(data) }; + drop(data); + } +} + +impl std::ops::Deref for Alloc { + type Target = T; + + fn deref(&self) -> &Self::Target { + unsafe { self.data.as_ref() } + } +} + +impl std::ops::DerefMut for Alloc { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { self.data.as_mut() } + } +} + +unsafe impl Send for Alloc where T: Send {} + +unsafe impl Sync for Alloc where T: Sync {} diff --git a/components/salsa-2022/src/interned.rs b/components/salsa-2022/src/interned.rs index 3739c684..987d3180 100644 --- a/components/salsa-2022/src/interned.rs +++ b/components/salsa-2022/src/interned.rs @@ -3,6 +3,7 @@ use std::fmt; use std::hash::Hash; use std::marker::PhantomData; +use crate::alloc::Alloc; use crate::durability::Durability; use crate::id::{AsId, LookupId}; use crate::ingredient::{fmt_index, IngredientRequiresReset}; @@ -39,7 +40,7 @@ pub struct InternedIngredient { /// Maps from an interned id to its data. /// /// Deadlock requirement: We access `value_map` while holding lock on `key_map`, but not vice versa. - value_map: FxDashMap>>, + value_map: FxDashMap>>, /// counter for the next id. counter: AtomicCell, @@ -121,7 +122,7 @@ where let value = self .value_map .entry(next_id) - .or_insert(Box::new(ValueStruct { + .or_insert(Alloc::new(ValueStruct { id: next_id, fields: internal_data, })); diff --git a/components/salsa-2022/src/lib.rs b/components/salsa-2022/src/lib.rs index c2c811d6..f0099b53 100644 --- a/components/salsa-2022/src/lib.rs +++ b/components/salsa-2022/src/lib.rs @@ -1,4 +1,5 @@ pub mod accumulator; +mod alloc; pub mod cancelled; pub mod cycle; pub mod database; diff --git a/components/salsa-2022/src/tracked_struct/struct_map.rs b/components/salsa-2022/src/tracked_struct/struct_map.rs index 399eec27..55b6ed20 100644 --- a/components/salsa-2022/src/tracked_struct/struct_map.rs +++ b/components/salsa-2022/src/tracked_struct/struct_map.rs @@ -7,6 +7,7 @@ use crossbeam::queue::SegQueue; use dashmap::mapref::one::RefMut; use crate::{ + alloc::Alloc, hash::{FxDashMap, FxHasher}, plumbing::transmute_lifetime, Id, Runtime, @@ -18,21 +19,21 @@ pub(crate) struct StructMap where C: Configuration, { - map: Arc>>>, + map: Arc>>>, /// When specific entities are deleted, their data is added /// to this vector rather than being immediately freed. This is because we may` have /// references to that data floating about that are tied to the lifetime of some /// `&db` reference. This queue itself is not freed until we have an `&mut db` reference, /// guaranteeing that there are no more references to it. - deleted_entries: SegQueue>>, + deleted_entries: SegQueue>>, } pub(crate) struct StructMapView where C: Configuration, { - map: Arc>>>, + map: Arc>>>, } /// Return value for [`StructMap`][]'s `update` method. @@ -79,7 +80,7 @@ where pub fn insert<'db>(&'db self, runtime: &'db Runtime, value: ValueStruct) -> &ValueStruct { assert_eq!(value.created_at, runtime.current_revision()); - let boxed_value = Box::new(value); + let boxed_value = Alloc::new(value); let pointer = std::ptr::addr_of!(*boxed_value); let old_value = self.map.insert(boxed_value.id, boxed_value); @@ -165,7 +166,7 @@ where /// * If the value is not present in the map. /// * If the value has not been updated in this revision. fn get_from_map<'db>( - map: &'db FxDashMap>>, + map: &'db FxDashMap>>, runtime: &'db Runtime, id: Id, ) -> &'db ValueStruct { @@ -230,7 +231,7 @@ pub(crate) struct UpdateRef<'db, C> where C: Configuration, { - guard: RefMut<'db, Id, Box>, FxHasher>, + guard: RefMut<'db, Id, Alloc>, FxHasher>, } impl<'db, C> UpdateRef<'db, C>