mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-15 09:48:53 +00:00
use Alloc not Box
to avoid uniqueness guarantees
This commit is contained in:
parent
a7b2805b06
commit
81942f37e5
4 changed files with 53 additions and 8 deletions
42
components/salsa-2022/src/alloc.rs
Normal file
42
components/salsa-2022/src/alloc.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use std::ptr::NonNull;
|
||||
|
||||
/// A box but without the uniqueness guarantees.
|
||||
pub struct Alloc<T> {
|
||||
data: NonNull<T>,
|
||||
}
|
||||
|
||||
impl<T> Alloc<T> {
|
||||
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<T> Drop for Alloc<T> {
|
||||
fn drop(&mut self) {
|
||||
let data: *mut T = self.data.as_ptr();
|
||||
let data: Box<T> = unsafe { Box::from_raw(data) };
|
||||
drop(data);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::Deref for Alloc<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { self.data.as_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::DerefMut for Alloc<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe { self.data.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> Send for Alloc<T> where T: Send {}
|
||||
|
||||
unsafe impl<T> Sync for Alloc<T> where T: Sync {}
|
|
@ -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<C: Configuration> {
|
|||
/// 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<Id, Box<ValueStruct<C>>>,
|
||||
value_map: FxDashMap<Id, Alloc<ValueStruct<C>>>,
|
||||
|
||||
/// counter for the next id.
|
||||
counter: AtomicCell<u32>,
|
||||
|
@ -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,
|
||||
}));
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
pub mod accumulator;
|
||||
mod alloc;
|
||||
pub mod cancelled;
|
||||
pub mod cycle;
|
||||
pub mod database;
|
||||
|
|
|
@ -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<C>
|
|||
where
|
||||
C: Configuration,
|
||||
{
|
||||
map: Arc<FxDashMap<Id, Box<ValueStruct<C>>>>,
|
||||
map: Arc<FxDashMap<Id, Alloc<ValueStruct<C>>>>,
|
||||
|
||||
/// 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<Box<ValueStruct<C>>>,
|
||||
deleted_entries: SegQueue<Alloc<ValueStruct<C>>>,
|
||||
}
|
||||
|
||||
pub(crate) struct StructMapView<C>
|
||||
where
|
||||
C: Configuration,
|
||||
{
|
||||
map: Arc<FxDashMap<Id, Box<ValueStruct<C>>>>,
|
||||
map: Arc<FxDashMap<Id, Alloc<ValueStruct<C>>>>,
|
||||
}
|
||||
|
||||
/// Return value for [`StructMap`][]'s `update` method.
|
||||
|
@ -79,7 +80,7 @@ where
|
|||
pub fn insert<'db>(&'db self, runtime: &'db Runtime, value: ValueStruct<C>) -> &ValueStruct<C> {
|
||||
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<Id, Box<ValueStruct<C>>>,
|
||||
map: &'db FxDashMap<Id, Alloc<ValueStruct<C>>>,
|
||||
runtime: &'db Runtime,
|
||||
id: Id,
|
||||
) -> &'db ValueStruct<C> {
|
||||
|
@ -230,7 +231,7 @@ pub(crate) struct UpdateRef<'db, C>
|
|||
where
|
||||
C: Configuration,
|
||||
{
|
||||
guard: RefMut<'db, Id, Box<ValueStruct<C>>, FxHasher>,
|
||||
guard: RefMut<'db, Id, Alloc<ValueStruct<C>>, FxHasher>,
|
||||
}
|
||||
|
||||
impl<'db, C> UpdateRef<'db, C>
|
||||
|
|
Loading…
Reference in a new issue