return &TrackedStructValue<C> from new_struct

This is a step towards the goal of keep a pointer
in the structs themselves.
This commit is contained in:
Niko Matsakis 2024-04-12 05:12:38 -04:00
parent 4533cd9e4b
commit e24ace24eb
3 changed files with 58 additions and 27 deletions

View file

@ -57,6 +57,7 @@ impl TrackedStruct {
let ingredients_for_impl = self.tracked_struct_ingredients(&config_struct);
let salsa_struct_in_db_impl = self.salsa_struct_in_db_impl();
let tracked_struct_in_db_impl = self.tracked_struct_in_db_impl();
let update_impl = self.update_impl();
let as_id_impl = self.as_id_impl();
let as_debug_with_db_impl = self.as_debug_with_db_impl();
Ok(quote! {
@ -67,6 +68,7 @@ impl TrackedStruct {
#ingredients_for_impl
#salsa_struct_in_db_impl
#tracked_struct_in_db_impl
#update_impl
#as_id_impl
#as_debug_with_db_impl
})
@ -210,11 +212,11 @@ impl TrackedStruct {
{
let (__jar, __runtime) = <_ as salsa::storage::HasJar<#jar_ty>>::jar(__db);
let __ingredients = <#jar_ty as salsa::storage::HasIngredientsFor< #ident >>::ingredient(__jar);
let __id = __ingredients.0.new_struct(
let __data = __ingredients.0.new_struct(
__runtime,
(#(#field_names,)*),
);
__id
__data.id()
}
#(#field_getters)*
@ -332,6 +334,22 @@ impl TrackedStruct {
}
}
/// Implementation of `Update`.
fn update_impl(&self) -> syn::ItemImpl {
let ident = self.id_ident();
parse_quote! {
unsafe impl salsa::update::Update for #ident {
unsafe fn maybe_update(old_pointer: *mut Self, new_value: Self) -> bool {
if unsafe { *old_pointer } != new_value {
unsafe { *old_pointer = new_value };
true
} else {
false
}
}
}
}
}
/// The index of the tracked struct ingredient in the ingredient tuple.
fn tracked_struct_ingredient_index(&self) -> Literal {
Literal::usize_unsuffixed(0)

View file

@ -10,6 +10,7 @@ use crate::{
ingredient_list::IngredientList,
interned::{InternedId, InternedIngredient},
key::{DatabaseKeyIndex, DependencyIndex},
plumbing::transmute_lifetime,
runtime::{local_state::QueryOrigin, Runtime},
salsa_struct::SalsaStructInDb,
Database, Durability, Event, IngredientIndex, Revision,
@ -125,10 +126,13 @@ struct TrackedStructKey {
// ANCHOR: TrackedStructValue
#[derive(Debug)]
struct TrackedStructValue<C>
pub struct TrackedStructValue<C>
where
C: Configuration,
{
/// The id of this struct in the ingredient.
id: C::Id,
/// The durability minimum durability of all inputs consumed
/// by the creator query prior to creating this tracked struct.
/// If any of those inputs changes, then the creator query may
@ -155,6 +159,16 @@ where
}
// ANCHOR_END: TrackedStructValue
impl<C> TrackedStructValue<C>
where
C: Configuration,
{
/// The id of this struct in the ingredient.
pub fn id(&self) -> C::Id {
self.id
}
}
#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone)]
pub struct Disambiguator(pub u32);
@ -194,7 +208,7 @@ where
}
}
pub fn new_struct(&self, runtime: &Runtime, fields: C::Fields) -> C::Id {
pub fn new_struct(&self, runtime: &Runtime, fields: C::Fields) -> &TrackedStructValue<C> {
let data_hash = crate::hash::hash(&C::id_fields(&fields));
let (query_key, current_deps, disambiguator) = runtime.disambiguate_entity(
@ -211,22 +225,29 @@ where
let (id, new_id) = self.interned.intern_full(runtime, entity_key);
runtime.add_output(self.database_key_index(id).into());
let pointer: *const TrackedStructValue<C>;
let current_revision = runtime.current_revision();
if new_id {
let old_value = self.entity_data.insert(
let data = Box::new(TrackedStructValue {
id,
Box::new(TrackedStructValue {
created_at: current_revision,
durability: current_deps.durability,
fields,
revisions: C::new_revisions(current_deps.changed_at),
}),
);
created_at: current_revision,
durability: current_deps.durability,
fields,
revisions: C::new_revisions(current_deps.changed_at),
});
// Keep a pointer into the box for later
pointer = &*data;
let old_value = self.entity_data.insert(id, data);
assert!(old_value.is_none());
} else {
let mut data = self.entity_data.get_mut(&id).unwrap();
let data = &mut *data;
// Keep a pointer into the box for later
pointer = &**data;
// SAFETY: We assert that the pointer to `data.revisions`
// is a pointer into the database referencing a value
// from a previous revision. As such, it continues to meet
@ -247,7 +268,13 @@ where
data.durability = current_deps.durability;
}
id
// Unsafety clause:
//
// * The box is owned by self and, although the box has been moved,
// the pointer is to the contents of the box, which have a stable
// address.
// * Values are only removed or altered when we have `&mut self`.
unsafe { transmute_lifetime(self, &*pointer) }
}
/// Deletes the given entities. This is used after a query `Q` executes and we can compare

View file

@ -126,20 +126,6 @@ pub unsafe trait Update {
unsafe fn maybe_update(old_pointer: *mut Self, new_value: Self) -> bool;
}
unsafe impl<T> Update for &T {
unsafe fn maybe_update(old_pointer: *mut Self, new_value: Self) -> bool {
let old_value: *const T = unsafe { *old_pointer };
if old_value != (new_value as *const T) {
unsafe {
*old_pointer = new_value;
}
true
} else {
false
}
}
}
unsafe impl<T> Update for Vec<T>
where
T: Update,