mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-02-08 21:35:47 +00:00
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:
parent
4533cd9e4b
commit
e24ace24eb
3 changed files with 58 additions and 27 deletions
|
@ -57,6 +57,7 @@ impl TrackedStruct {
|
||||||
let ingredients_for_impl = self.tracked_struct_ingredients(&config_struct);
|
let ingredients_for_impl = self.tracked_struct_ingredients(&config_struct);
|
||||||
let salsa_struct_in_db_impl = self.salsa_struct_in_db_impl();
|
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 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_id_impl = self.as_id_impl();
|
||||||
let as_debug_with_db_impl = self.as_debug_with_db_impl();
|
let as_debug_with_db_impl = self.as_debug_with_db_impl();
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
|
@ -67,6 +68,7 @@ impl TrackedStruct {
|
||||||
#ingredients_for_impl
|
#ingredients_for_impl
|
||||||
#salsa_struct_in_db_impl
|
#salsa_struct_in_db_impl
|
||||||
#tracked_struct_in_db_impl
|
#tracked_struct_in_db_impl
|
||||||
|
#update_impl
|
||||||
#as_id_impl
|
#as_id_impl
|
||||||
#as_debug_with_db_impl
|
#as_debug_with_db_impl
|
||||||
})
|
})
|
||||||
|
@ -210,11 +212,11 @@ impl TrackedStruct {
|
||||||
{
|
{
|
||||||
let (__jar, __runtime) = <_ as salsa::storage::HasJar<#jar_ty>>::jar(__db);
|
let (__jar, __runtime) = <_ as salsa::storage::HasJar<#jar_ty>>::jar(__db);
|
||||||
let __ingredients = <#jar_ty as salsa::storage::HasIngredientsFor< #ident >>::ingredient(__jar);
|
let __ingredients = <#jar_ty as salsa::storage::HasIngredientsFor< #ident >>::ingredient(__jar);
|
||||||
let __id = __ingredients.0.new_struct(
|
let __data = __ingredients.0.new_struct(
|
||||||
__runtime,
|
__runtime,
|
||||||
(#(#field_names,)*),
|
(#(#field_names,)*),
|
||||||
);
|
);
|
||||||
__id
|
__data.id()
|
||||||
}
|
}
|
||||||
|
|
||||||
#(#field_getters)*
|
#(#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.
|
/// The index of the tracked struct ingredient in the ingredient tuple.
|
||||||
fn tracked_struct_ingredient_index(&self) -> Literal {
|
fn tracked_struct_ingredient_index(&self) -> Literal {
|
||||||
Literal::usize_unsuffixed(0)
|
Literal::usize_unsuffixed(0)
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::{
|
||||||
ingredient_list::IngredientList,
|
ingredient_list::IngredientList,
|
||||||
interned::{InternedId, InternedIngredient},
|
interned::{InternedId, InternedIngredient},
|
||||||
key::{DatabaseKeyIndex, DependencyIndex},
|
key::{DatabaseKeyIndex, DependencyIndex},
|
||||||
|
plumbing::transmute_lifetime,
|
||||||
runtime::{local_state::QueryOrigin, Runtime},
|
runtime::{local_state::QueryOrigin, Runtime},
|
||||||
salsa_struct::SalsaStructInDb,
|
salsa_struct::SalsaStructInDb,
|
||||||
Database, Durability, Event, IngredientIndex, Revision,
|
Database, Durability, Event, IngredientIndex, Revision,
|
||||||
|
@ -125,10 +126,13 @@ struct TrackedStructKey {
|
||||||
|
|
||||||
// ANCHOR: TrackedStructValue
|
// ANCHOR: TrackedStructValue
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct TrackedStructValue<C>
|
pub struct TrackedStructValue<C>
|
||||||
where
|
where
|
||||||
C: Configuration,
|
C: Configuration,
|
||||||
{
|
{
|
||||||
|
/// The id of this struct in the ingredient.
|
||||||
|
id: C::Id,
|
||||||
|
|
||||||
/// The durability minimum durability of all inputs consumed
|
/// The durability minimum durability of all inputs consumed
|
||||||
/// by the creator query prior to creating this tracked struct.
|
/// by the creator query prior to creating this tracked struct.
|
||||||
/// If any of those inputs changes, then the creator query may
|
/// If any of those inputs changes, then the creator query may
|
||||||
|
@ -155,6 +159,16 @@ where
|
||||||
}
|
}
|
||||||
// ANCHOR_END: TrackedStructValue
|
// 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)]
|
#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone)]
|
||||||
pub struct Disambiguator(pub u32);
|
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 data_hash = crate::hash::hash(&C::id_fields(&fields));
|
||||||
|
|
||||||
let (query_key, current_deps, disambiguator) = runtime.disambiguate_entity(
|
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);
|
let (id, new_id) = self.interned.intern_full(runtime, entity_key);
|
||||||
runtime.add_output(self.database_key_index(id).into());
|
runtime.add_output(self.database_key_index(id).into());
|
||||||
|
|
||||||
|
let pointer: *const TrackedStructValue<C>;
|
||||||
let current_revision = runtime.current_revision();
|
let current_revision = runtime.current_revision();
|
||||||
if new_id {
|
if new_id {
|
||||||
let old_value = self.entity_data.insert(
|
let data = Box::new(TrackedStructValue {
|
||||||
id,
|
id,
|
||||||
Box::new(TrackedStructValue {
|
created_at: current_revision,
|
||||||
created_at: current_revision,
|
durability: current_deps.durability,
|
||||||
durability: current_deps.durability,
|
fields,
|
||||||
fields,
|
revisions: C::new_revisions(current_deps.changed_at),
|
||||||
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());
|
assert!(old_value.is_none());
|
||||||
} else {
|
} else {
|
||||||
let mut data = self.entity_data.get_mut(&id).unwrap();
|
let mut data = self.entity_data.get_mut(&id).unwrap();
|
||||||
let data = &mut *data;
|
let data = &mut *data;
|
||||||
|
|
||||||
|
// Keep a pointer into the box for later
|
||||||
|
pointer = &**data;
|
||||||
|
|
||||||
// SAFETY: We assert that the pointer to `data.revisions`
|
// SAFETY: We assert that the pointer to `data.revisions`
|
||||||
// is a pointer into the database referencing a value
|
// is a pointer into the database referencing a value
|
||||||
// from a previous revision. As such, it continues to meet
|
// from a previous revision. As such, it continues to meet
|
||||||
|
@ -247,7 +268,13 @@ where
|
||||||
data.durability = current_deps.durability;
|
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
|
/// Deletes the given entities. This is used after a query `Q` executes and we can compare
|
||||||
|
|
|
@ -126,20 +126,6 @@ pub unsafe trait Update {
|
||||||
unsafe fn maybe_update(old_pointer: *mut Self, new_value: Self) -> bool;
|
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>
|
unsafe impl<T> Update for Vec<T>
|
||||||
where
|
where
|
||||||
T: Update,
|
T: Update,
|
||||||
|
|
Loading…
Reference in a new issue