rustfmt
This commit is contained in:
parent
159a03ad7b
commit
0a6197df97
@ -108,9 +108,7 @@ fn slot(&self, key: &Q::Key) -> Arc<Slot<Q, MP>> {
|
||||
query_index: Q::QUERY_INDEX,
|
||||
key_index,
|
||||
};
|
||||
entry
|
||||
.or_insert_with(|| Arc::new(Slot::new(key.clone(), database_key_index)))
|
||||
.clone()
|
||||
entry.or_insert_with(|| Arc::new(Slot::new(key.clone(), database_key_index))).clone()
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,13 +150,7 @@ fn maybe_changed_after(
|
||||
assert_eq!(input.group_index, self.group_index);
|
||||
assert_eq!(input.query_index, Q::QUERY_INDEX);
|
||||
debug_assert!(revision < db.salsa_runtime().current_revision());
|
||||
let slot = self
|
||||
.slot_map
|
||||
.read()
|
||||
.get_index(input.key_index as usize)
|
||||
.unwrap()
|
||||
.1
|
||||
.clone();
|
||||
let slot = self.slot_map.read().get_index(input.key_index as usize).unwrap().1.clone();
|
||||
slot.maybe_changed_after(db, revision)
|
||||
}
|
||||
|
||||
@ -166,22 +158,17 @@ fn fetch(&self, db: &<Q as QueryDb<'_>>::DynDb, key: &Q::Key) -> Q::Value {
|
||||
db.unwind_if_cancelled();
|
||||
|
||||
let slot = self.slot(key);
|
||||
let StampedValue {
|
||||
value,
|
||||
durability,
|
||||
changed_at,
|
||||
} = slot.read(db);
|
||||
let StampedValue { value, durability, changed_at } = slot.read(db);
|
||||
|
||||
if let Some(evicted) = self.lru_list.record_use(&slot) {
|
||||
evicted.evict();
|
||||
}
|
||||
|
||||
db.salsa_runtime()
|
||||
.report_query_read_and_unwind_if_cycle_resulted(
|
||||
slot.database_key_index(),
|
||||
durability,
|
||||
changed_at,
|
||||
);
|
||||
db.salsa_runtime().report_query_read_and_unwind_if_cycle_resulted(
|
||||
slot.database_key_index(),
|
||||
durability,
|
||||
changed_at,
|
||||
);
|
||||
|
||||
value
|
||||
}
|
||||
@ -195,10 +182,7 @@ fn entries<C>(&self, _db: &<Q as QueryDb<'_>>::DynDb) -> C
|
||||
C: std::iter::FromIterator<TableEntry<Q::Key, Q::Value>>,
|
||||
{
|
||||
let slot_map = self.slot_map.read();
|
||||
slot_map
|
||||
.values()
|
||||
.filter_map(|slot| slot.as_table_entry())
|
||||
.collect()
|
||||
slot_map.values().filter_map(|slot| slot.as_table_entry()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,14 +209,7 @@ fn read_upgrade(
|
||||
}
|
||||
}
|
||||
|
||||
self.execute(
|
||||
db,
|
||||
runtime,
|
||||
revision_now,
|
||||
active_query,
|
||||
panic_guard,
|
||||
old_memo,
|
||||
)
|
||||
self.execute(db, runtime, revision_now, active_query, panic_guard, old_memo)
|
||||
}
|
||||
|
||||
fn execute(
|
||||
@ -232,9 +225,7 @@ fn execute(
|
||||
|
||||
db.salsa_event(Event {
|
||||
runtime_id: db.salsa_runtime().id(),
|
||||
kind: EventKind::WillExecute {
|
||||
database_key: self.database_key_index,
|
||||
},
|
||||
kind: EventKind::WillExecute { database_key: self.database_key_index },
|
||||
});
|
||||
|
||||
// Query was not previously executed, or value is potentially
|
||||
@ -310,22 +301,12 @@ fn execute(
|
||||
changed_at: revisions.changed_at,
|
||||
};
|
||||
|
||||
let memo_value = if self.should_memoize_value(&self.key) {
|
||||
Some(new_value.value.clone())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let memo_value =
|
||||
if self.should_memoize_value(&self.key) { Some(new_value.value.clone()) } else { None };
|
||||
|
||||
debug!(
|
||||
"read_upgrade({:?}): result.revisions = {:#?}",
|
||||
self, revisions,
|
||||
);
|
||||
debug!("read_upgrade({:?}): result.revisions = {:#?}", self, revisions,);
|
||||
|
||||
panic_guard.proceed(Some(Memo {
|
||||
value: memo_value,
|
||||
verified_at: revision_now,
|
||||
revisions,
|
||||
}));
|
||||
panic_guard.proceed(Some(Memo { value: memo_value, verified_at: revision_now, revisions }));
|
||||
|
||||
new_value
|
||||
}
|
||||
@ -388,10 +369,7 @@ fn probe<StateGuard>(
|
||||
value: value.clone(),
|
||||
};
|
||||
|
||||
info!(
|
||||
"{:?}: returning memoized value changed at {:?}",
|
||||
self, value.changed_at
|
||||
);
|
||||
info!("{:?}: returning memoized value changed at {:?}", self, value.changed_at);
|
||||
|
||||
ProbeState::UpToDate(value)
|
||||
} else {
|
||||
@ -503,11 +481,9 @@ fn maybe_changed_after_probe<StateGuard>(
|
||||
// If we know when value last changed, we can return right away.
|
||||
// Note that we don't need the actual value to be available.
|
||||
ProbeState::NoValue(_, changed_at)
|
||||
| ProbeState::UpToDate(StampedValue {
|
||||
value: _,
|
||||
durability: _,
|
||||
changed_at,
|
||||
}) => MaybeChangedSinceProbeState::ChangedAt(changed_at),
|
||||
| ProbeState::UpToDate(StampedValue { value: _, durability: _, changed_at }) => {
|
||||
MaybeChangedSinceProbeState::ChangedAt(changed_at)
|
||||
}
|
||||
|
||||
// If we have nothing cached, then value may have changed.
|
||||
ProbeState::NotComputed(_) => MaybeChangedSinceProbeState::ChangedAt(revision_now),
|
||||
@ -561,14 +537,8 @@ fn maybe_changed_after_upgrade(
|
||||
// We found that this memoized value may have changed
|
||||
// but we have an old value. We can re-run the code and
|
||||
// actually *check* if it has changed.
|
||||
let StampedValue { changed_at, .. } = self.execute(
|
||||
db,
|
||||
runtime,
|
||||
revision_now,
|
||||
active_query,
|
||||
panic_guard,
|
||||
Some(old_memo),
|
||||
);
|
||||
let StampedValue { changed_at, .. } =
|
||||
self.execute(db, runtime, revision_now, active_query, panic_guard, Some(old_memo));
|
||||
changed_at > revision
|
||||
} else {
|
||||
// We found that inputs to this memoized value may have chanced
|
||||
@ -605,10 +575,7 @@ impl<Q> QueryState<Q>
|
||||
Q: QueryFunction,
|
||||
{
|
||||
fn in_progress(id: RuntimeId) -> Self {
|
||||
QueryState::InProgress {
|
||||
id,
|
||||
anyone_waiting: Default::default(),
|
||||
}
|
||||
QueryState::InProgress { id, anyone_waiting: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -632,11 +599,7 @@ fn new(
|
||||
slot: &'me Slot<Q, MP>,
|
||||
runtime: &'me Runtime,
|
||||
) -> Self {
|
||||
Self {
|
||||
database_key_index,
|
||||
slot,
|
||||
runtime,
|
||||
}
|
||||
Self { database_key_index, slot, runtime }
|
||||
}
|
||||
|
||||
/// Indicates that we have concluded normally (without panicking).
|
||||
@ -674,8 +637,7 @@ fn overwrite_placeholder(&mut self, wait_result: WaitResult, opt_memo: Option<Me
|
||||
// acquire a mutex; the mutex will guarantee that all writes
|
||||
// we are interested in are visible.
|
||||
if anyone_waiting.load(Ordering::Relaxed) {
|
||||
self.runtime
|
||||
.unblock_queries_blocked_on(self.database_key_index, wait_result);
|
||||
self.runtime.unblock_queries_blocked_on(self.database_key_index, wait_result);
|
||||
}
|
||||
}
|
||||
_ => panic!(
|
||||
@ -784,9 +746,8 @@ fn verify_revisions(
|
||||
// are only interested in finding out whether the
|
||||
// input changed *again*.
|
||||
QueryInputs::Tracked { inputs } => {
|
||||
let changed_input = inputs
|
||||
.iter()
|
||||
.find(|&&input| db.maybe_changed_after(input, verified_at));
|
||||
let changed_input =
|
||||
inputs.iter().find(|&&input| db.maybe_changed_after(input, verified_at));
|
||||
if let Some(input) = changed_input {
|
||||
debug!("validate_memoized_value: `{:?}` may have changed", input);
|
||||
|
||||
|
@ -50,10 +50,7 @@ impl<Q> QueryStorageOps<Q> for InputStorage<Q>
|
||||
const CYCLE_STRATEGY: crate::plumbing::CycleRecoveryStrategy = CycleRecoveryStrategy::Panic;
|
||||
|
||||
fn new(group_index: u16) -> Self {
|
||||
InputStorage {
|
||||
group_index,
|
||||
slots: Default::default(),
|
||||
}
|
||||
InputStorage { group_index, slots: Default::default() }
|
||||
}
|
||||
|
||||
fn fmt_index(
|
||||
@ -91,18 +88,13 @@ fn fetch(&self, db: &<Q as QueryDb<'_>>::DynDb, key: &Q::Key) -> Q::Value {
|
||||
.get(key)
|
||||
.unwrap_or_else(|| panic!("no value set for {:?}({:?})", Q::default(), key));
|
||||
|
||||
let StampedValue {
|
||||
value,
|
||||
let StampedValue { value, durability, changed_at } = slot.stamped_value.read().clone();
|
||||
|
||||
db.salsa_runtime().report_query_read_and_unwind_if_cycle_resulted(
|
||||
slot.database_key_index,
|
||||
durability,
|
||||
changed_at,
|
||||
} = slot.stamped_value.read().clone();
|
||||
|
||||
db.salsa_runtime()
|
||||
.report_query_read_and_unwind_if_cycle_resulted(
|
||||
slot.database_key_index,
|
||||
durability,
|
||||
changed_at,
|
||||
);
|
||||
);
|
||||
|
||||
value
|
||||
}
|
||||
@ -133,10 +125,7 @@ impl<Q> Slot<Q>
|
||||
Q: Query,
|
||||
{
|
||||
fn maybe_changed_after(&self, _db: &<Q as QueryDb<'_>>::DynDb, revision: Revision) -> bool {
|
||||
debug!(
|
||||
"maybe_changed_after(slot={:?}, revision={:?})",
|
||||
self, revision,
|
||||
);
|
||||
debug!("maybe_changed_after(slot={:?}, revision={:?})", self, revision,);
|
||||
|
||||
let changed_at = self.stamped_value.read().changed_at;
|
||||
|
||||
@ -160,13 +149,7 @@ impl<Q> InputQueryStorageOps<Q> for InputStorage<Q>
|
||||
Q: Query,
|
||||
{
|
||||
fn set(&self, runtime: &mut Runtime, key: &Q::Key, value: Q::Value, durability: Durability) {
|
||||
tracing::debug!(
|
||||
"{:?}({:?}) = {:?} ({:?})",
|
||||
Q::default(),
|
||||
key,
|
||||
value,
|
||||
durability
|
||||
);
|
||||
tracing::debug!("{:?}({:?}) = {:?} ({:?})", Q::default(), key, value, durability);
|
||||
|
||||
// The value is changing, so we need a new revision (*). We also
|
||||
// need to update the 'last changed' revision by invoking
|
||||
@ -190,11 +173,7 @@ fn set(&self, runtime: &mut Runtime, key: &Q::Key, value: Q::Value, durability:
|
||||
// racing with somebody else to modify this same cell.
|
||||
// (Otherwise, someone else might write a *newer* revision
|
||||
// into the same cell while we block on the lock.)
|
||||
let stamped_value = StampedValue {
|
||||
value,
|
||||
durability,
|
||||
changed_at: next_revision,
|
||||
};
|
||||
let stamped_value = StampedValue { value, durability, changed_at: next_revision };
|
||||
|
||||
match slots.entry(key.clone()) {
|
||||
Entry::Occupied(entry) => {
|
||||
|
@ -63,9 +63,7 @@ impl InternId {
|
||||
/// `value` must be less than `MAX`
|
||||
pub const unsafe fn new_unchecked(value: u32) -> Self {
|
||||
debug_assert!(value < InternId::MAX);
|
||||
InternId {
|
||||
value: NonZeroU32::new_unchecked(value + 1),
|
||||
}
|
||||
InternId { value: NonZeroU32::new_unchecked(value + 1) }
|
||||
}
|
||||
|
||||
/// Convert this raw-id into a u32 value.
|
||||
|
@ -110,10 +110,7 @@ impl<K> Default for InternTables<K>
|
||||
K: Eq + Hash,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
map: Default::default(),
|
||||
values: Default::default(),
|
||||
}
|
||||
Self { map: Default::default(), values: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,11 +156,7 @@ fn intern_index(
|
||||
query_index: Q::QUERY_INDEX,
|
||||
key_index: index.as_u32(),
|
||||
};
|
||||
Arc::new(Slot {
|
||||
database_key_index,
|
||||
value: owned_key2,
|
||||
interned_at: revision_now,
|
||||
})
|
||||
Arc::new(Slot { database_key_index, value: owned_key2, interned_at: revision_now })
|
||||
};
|
||||
|
||||
let (slot, index);
|
||||
@ -194,10 +187,7 @@ impl<Q> QueryStorageOps<Q> for InternedStorage<Q>
|
||||
const CYCLE_STRATEGY: crate::plumbing::CycleRecoveryStrategy = CycleRecoveryStrategy::Panic;
|
||||
|
||||
fn new(group_index: u16) -> Self {
|
||||
InternedStorage {
|
||||
group_index,
|
||||
tables: RwLock::new(InternTables::default()),
|
||||
}
|
||||
InternedStorage { group_index, tables: RwLock::new(InternTables::default()) }
|
||||
}
|
||||
|
||||
fn fmt_index(
|
||||
@ -231,12 +221,11 @@ fn fetch(&self, db: &<Q as QueryDb<'_>>::DynDb, key: &Q::Key) -> Q::Value {
|
||||
db.unwind_if_cancelled();
|
||||
let (slot, index) = self.intern_index(db, key);
|
||||
let changed_at = slot.interned_at;
|
||||
db.salsa_runtime()
|
||||
.report_query_read_and_unwind_if_cycle_resulted(
|
||||
slot.database_key_index,
|
||||
INTERN_DURABILITY,
|
||||
changed_at,
|
||||
);
|
||||
db.salsa_runtime().report_query_read_and_unwind_if_cycle_resulted(
|
||||
slot.database_key_index,
|
||||
INTERN_DURABILITY,
|
||||
changed_at,
|
||||
);
|
||||
<Q::Value>::from_intern_id(index)
|
||||
}
|
||||
|
||||
@ -313,9 +302,7 @@ impl<Q, IQ> QueryStorageOps<Q> for LookupInternedStorage<Q, IQ>
|
||||
const CYCLE_STRATEGY: CycleRecoveryStrategy = CycleRecoveryStrategy::Panic;
|
||||
|
||||
fn new(_group_index: u16) -> Self {
|
||||
LookupInternedStorage {
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
LookupInternedStorage { phantom: std::marker::PhantomData }
|
||||
}
|
||||
|
||||
fn fmt_index(
|
||||
@ -350,12 +337,11 @@ fn fetch(&self, db: &<Q as QueryDb<'_>>::DynDb, key: &Q::Key) -> Q::Value {
|
||||
let slot = interned_storage.lookup_value(index);
|
||||
let value = slot.value.clone();
|
||||
let interned_at = slot.interned_at;
|
||||
db.salsa_runtime()
|
||||
.report_query_read_and_unwind_if_cycle_resulted(
|
||||
slot.database_key_index,
|
||||
INTERN_DURABILITY,
|
||||
interned_at,
|
||||
);
|
||||
db.salsa_runtime().report_query_read_and_unwind_if_cycle_resulted(
|
||||
slot.database_key_index,
|
||||
INTERN_DURABILITY,
|
||||
interned_at,
|
||||
);
|
||||
value
|
||||
}
|
||||
|
||||
|
@ -216,18 +216,14 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
.debug_struct("DidValidateMemoizedValue")
|
||||
.field("database_key", database_key)
|
||||
.finish(),
|
||||
EventKind::WillBlockOn {
|
||||
other_runtime_id,
|
||||
database_key,
|
||||
} => fmt
|
||||
EventKind::WillBlockOn { other_runtime_id, database_key } => fmt
|
||||
.debug_struct("WillBlockOn")
|
||||
.field("other_runtime_id", other_runtime_id)
|
||||
.field("database_key", database_key)
|
||||
.finish(),
|
||||
EventKind::WillExecute { database_key } => fmt
|
||||
.debug_struct("WillExecute")
|
||||
.field("database_key", database_key)
|
||||
.finish(),
|
||||
EventKind::WillExecute { database_key } => {
|
||||
fmt.debug_struct("WillExecute").field("database_key", database_key).finish()
|
||||
}
|
||||
EventKind::WillCheckCancellation => fmt.debug_struct("WillCheckCancellation").finish(),
|
||||
}
|
||||
}
|
||||
@ -251,10 +247,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
.debug_struct("DidValidateMemoizedValue")
|
||||
.field("database_key", &database_key.debug(self.db))
|
||||
.finish(),
|
||||
EventKind::WillBlockOn {
|
||||
other_runtime_id,
|
||||
database_key,
|
||||
} => fmt
|
||||
EventKind::WillBlockOn { other_runtime_id, database_key } => fmt
|
||||
.debug_struct("WillBlockOn")
|
||||
.field("other_runtime_id", &other_runtime_id)
|
||||
.field("database_key", &database_key.debug(self.db))
|
||||
@ -707,9 +700,7 @@ pub fn participant_keys(&self) -> impl Iterator<Item = DatabaseKeyIndex> + '_ {
|
||||
/// Returns a vector with the debug information for
|
||||
/// all the participants in the cycle.
|
||||
pub fn all_participants<DB: ?Sized + Database>(&self, db: &DB) -> Vec<String> {
|
||||
self.participant_keys()
|
||||
.map(|d| format!("{:?}", d.debug(db)))
|
||||
.collect()
|
||||
self.participant_keys().map(|d| format!("{:?}", d.debug(db))).collect()
|
||||
}
|
||||
|
||||
/// Returns a vector with the debug information for
|
||||
@ -733,18 +724,12 @@ impl<'me> std::fmt::Debug for UnexpectedCycleDebug<'me> {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
fmt.debug_struct("UnexpectedCycle")
|
||||
.field("all_participants", &self.c.all_participants(self.db))
|
||||
.field(
|
||||
"unexpected_participants",
|
||||
&self.c.unexpected_participants(self.db),
|
||||
)
|
||||
.field("unexpected_participants", &self.c.unexpected_participants(self.db))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
UnexpectedCycleDebug {
|
||||
c: self,
|
||||
db: db.ops_database(),
|
||||
}
|
||||
UnexpectedCycleDebug { c: self, db: db.ops_database() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,10 +68,7 @@ pub fn new() -> Self {
|
||||
|
||||
#[cfg_attr(not(test), allow(dead_code))]
|
||||
fn with_seed(seed: &str) -> Self {
|
||||
Lru {
|
||||
green_zone: AtomicUsize::new(0),
|
||||
data: Mutex::new(LruData::with_seed(seed)),
|
||||
}
|
||||
Lru { green_zone: AtomicUsize::new(0), data: Mutex::new(LruData::with_seed(seed)) }
|
||||
}
|
||||
|
||||
/// Adjust the total number of nodes permitted to have a value at
|
||||
@ -143,13 +140,7 @@ fn with_seed(seed_str: &str) -> Self {
|
||||
}
|
||||
|
||||
fn with_rng(rng: Rand64) -> Self {
|
||||
LruData {
|
||||
end_yellow_zone: 0,
|
||||
end_green_zone: 0,
|
||||
end_red_zone: 0,
|
||||
entries: Vec::new(),
|
||||
rng,
|
||||
}
|
||||
LruData { end_yellow_zone: 0, end_green_zone: 0, end_red_zone: 0, entries: Vec::new(), rng }
|
||||
}
|
||||
|
||||
fn green_zone(&self) -> std::ops::Range<usize> {
|
||||
@ -294,9 +285,7 @@ fn pick_index(&mut self, zone: std::ops::Range<usize>) -> usize {
|
||||
|
||||
impl Default for LruIndex {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
index: AtomicUsize::new(std::usize::MAX),
|
||||
}
|
||||
Self { index: AtomicUsize::new(std::usize::MAX) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,10 +78,7 @@ fn cycle_fallback(
|
||||
key: &Self::Key,
|
||||
) -> Self::Value {
|
||||
let _ = (db, cycle, key);
|
||||
panic!(
|
||||
"query `{:?}` doesn't support cycle fallback",
|
||||
Self::default()
|
||||
)
|
||||
panic!("query `{:?}` doesn't support cycle fallback", Self::default())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,9 +21,7 @@ pub(crate) fn start() -> Self {
|
||||
}
|
||||
|
||||
pub(crate) fn from(g: u32) -> Self {
|
||||
Self {
|
||||
generation: NonZeroU32::new(g).unwrap(),
|
||||
}
|
||||
Self { generation: NonZeroU32::new(g).unwrap() }
|
||||
}
|
||||
|
||||
pub(crate) fn next(self) -> Revision {
|
||||
@ -48,9 +46,7 @@ pub(crate) struct AtomicRevision {
|
||||
|
||||
impl AtomicRevision {
|
||||
pub(crate) fn start() -> Self {
|
||||
Self {
|
||||
data: AtomicU32::new(START),
|
||||
}
|
||||
Self { data: AtomicU32::new(START) }
|
||||
}
|
||||
|
||||
pub(crate) fn load(&self) -> Revision {
|
||||
|
@ -85,9 +85,7 @@ pub(crate) fn snapshot(&self) -> Self {
|
||||
|
||||
let revision_guard = RevisionGuard::new(&self.shared_state);
|
||||
|
||||
let id = RuntimeId {
|
||||
counter: self.shared_state.next_id.fetch_add(1, Ordering::SeqCst),
|
||||
};
|
||||
let id = RuntimeId { counter: self.shared_state.next_id.fetch_add(1, Ordering::SeqCst) };
|
||||
|
||||
Runtime {
|
||||
id,
|
||||
@ -242,8 +240,7 @@ pub(crate) fn report_query_read_and_unwind_if_cycle_resulted(
|
||||
/// Queries which report untracked reads will be re-executed in the next
|
||||
/// revision.
|
||||
pub fn report_untracked_read(&self) {
|
||||
self.local_state
|
||||
.report_untracked_read(self.current_revision());
|
||||
self.local_state.report_untracked_read(self.current_revision());
|
||||
}
|
||||
|
||||
/// Acts as though the current query had read an input with the given durability; this will force the current query's durability to be at most `durability`.
|
||||
@ -251,8 +248,7 @@ pub fn report_untracked_read(&self) {
|
||||
/// This is mostly useful to control the durability level for [on-demand inputs](https://salsa-rs.github.io/salsa/common_patterns/on_demand_inputs.html).
|
||||
pub fn report_synthetic_read(&self, durability: Durability) {
|
||||
let changed_at = self.last_changed_revision(durability);
|
||||
self.local_state
|
||||
.report_synthetic_read(durability, changed_at);
|
||||
self.local_state.report_synthetic_read(durability, changed_at);
|
||||
}
|
||||
|
||||
/// Handles a cycle in the dependency graph that was detected when the
|
||||
@ -270,10 +266,7 @@ fn unblock_cycle_and_maybe_throw(
|
||||
database_key_index: DatabaseKeyIndex,
|
||||
to_id: RuntimeId,
|
||||
) {
|
||||
debug!(
|
||||
"unblock_cycle_and_maybe_throw(database_key={:?})",
|
||||
database_key_index
|
||||
);
|
||||
debug!("unblock_cycle_and_maybe_throw(database_key={:?})", database_key_index);
|
||||
|
||||
let mut from_stack = self.local_state.take_query_stack();
|
||||
let from_id = self.id();
|
||||
@ -312,11 +305,7 @@ fn unblock_cycle_and_maybe_throw(
|
||||
|
||||
Cycle::new(Arc::new(v))
|
||||
};
|
||||
debug!(
|
||||
"cycle {:?}, cycle_query {:#?}",
|
||||
cycle.debug(db),
|
||||
cycle_query,
|
||||
);
|
||||
debug!("cycle {:?}, cycle_query {:#?}", cycle.debug(db), cycle_query,);
|
||||
|
||||
// We can remove the cycle participants from the list of dependencies;
|
||||
// they are a strongly connected component (SCC) and we only care about
|
||||
@ -329,12 +318,10 @@ fn unblock_cycle_and_maybe_throw(
|
||||
// are going to be unwound so that fallback can occur.
|
||||
dg.for_each_cycle_participant(from_id, &mut from_stack, database_key_index, to_id, |aqs| {
|
||||
aqs.iter_mut()
|
||||
.skip_while(
|
||||
|aq| match db.cycle_recovery_strategy(aq.database_key_index) {
|
||||
CycleRecoveryStrategy::Panic => true,
|
||||
CycleRecoveryStrategy::Fallback => false,
|
||||
},
|
||||
)
|
||||
.skip_while(|aq| match db.cycle_recovery_strategy(aq.database_key_index) {
|
||||
CycleRecoveryStrategy::Panic => true,
|
||||
CycleRecoveryStrategy::Fallback => false,
|
||||
})
|
||||
.for_each(|aq| {
|
||||
debug!("marking {:?} for fallback", aq.database_key_index.debug(db));
|
||||
aq.take_inputs_from(&cycle_query);
|
||||
@ -404,10 +391,7 @@ pub(crate) fn block_on_or_unwind<QueryMutexGuard>(
|
||||
|
||||
db.salsa_event(Event {
|
||||
runtime_id: self.id(),
|
||||
kind: EventKind::WillBlockOn {
|
||||
other_runtime_id: other_id,
|
||||
database_key,
|
||||
},
|
||||
kind: EventKind::WillBlockOn { other_runtime_id: other_id, database_key },
|
||||
});
|
||||
|
||||
let stack = self.local_state.take_query_stack();
|
||||
@ -585,18 +569,12 @@ pub(crate) fn revisions(&self) -> QueryRevisions {
|
||||
if dependencies.is_empty() {
|
||||
QueryInputs::NoInputs
|
||||
} else {
|
||||
QueryInputs::Tracked {
|
||||
inputs: dependencies.iter().copied().collect(),
|
||||
}
|
||||
QueryInputs::Tracked { inputs: dependencies.iter().copied().collect() }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
QueryRevisions {
|
||||
changed_at: self.changed_at,
|
||||
inputs,
|
||||
durability: self.durability,
|
||||
}
|
||||
QueryRevisions { changed_at: self.changed_at, inputs, durability: self.durability }
|
||||
}
|
||||
|
||||
/// Adds any dependencies from `other` into `self`.
|
||||
@ -673,9 +651,7 @@ fn new(shared_state: &Arc<SharedState>) -> Self {
|
||||
shared_state.query_lock.raw().lock_shared_recursive();
|
||||
}
|
||||
|
||||
Self {
|
||||
shared_state: shared_state.clone(),
|
||||
}
|
||||
Self { shared_state: shared_state.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,21 +103,14 @@ pub(super) fn for_each_cycle_participant(
|
||||
// load up the next thread (i.e., we start at B/QB2,
|
||||
// and then load up the dependency on C/QC2).
|
||||
let edge = self.edges.get_mut(&id).unwrap();
|
||||
let prefix = edge
|
||||
.stack
|
||||
.iter_mut()
|
||||
.take_while(|p| p.database_key_index != key)
|
||||
.count();
|
||||
let prefix = edge.stack.iter_mut().take_while(|p| p.database_key_index != key).count();
|
||||
closure(&mut edge.stack[prefix..]);
|
||||
id = edge.blocked_on_id;
|
||||
key = edge.blocked_on_key;
|
||||
}
|
||||
|
||||
// Finally, we copy in the results from `from_stack`.
|
||||
let prefix = from_stack
|
||||
.iter_mut()
|
||||
.take_while(|p| p.database_key_index != key)
|
||||
.count();
|
||||
let prefix = from_stack.iter_mut().take_while(|p| p.database_key_index != key).count();
|
||||
closure(&mut from_stack[prefix..]);
|
||||
}
|
||||
|
||||
@ -141,24 +134,13 @@ pub(super) fn maybe_unblock_runtimes_in_cycle(
|
||||
let mut others_unblocked = false;
|
||||
while id != from_id {
|
||||
let edge = self.edges.get(&id).unwrap();
|
||||
let prefix = edge
|
||||
.stack
|
||||
.iter()
|
||||
.take_while(|p| p.database_key_index != key)
|
||||
.count();
|
||||
let prefix = edge.stack.iter().take_while(|p| p.database_key_index != key).count();
|
||||
let next_id = edge.blocked_on_id;
|
||||
let next_key = edge.blocked_on_key;
|
||||
|
||||
if let Some(cycle) = edge.stack[prefix..]
|
||||
.iter()
|
||||
.rev()
|
||||
.find_map(|aq| aq.cycle.clone())
|
||||
{
|
||||
if let Some(cycle) = edge.stack[prefix..].iter().rev().find_map(|aq| aq.cycle.clone()) {
|
||||
// Remove `id` from the list of runtimes blocked on `next_key`:
|
||||
self.query_dependents
|
||||
.get_mut(&next_key)
|
||||
.unwrap()
|
||||
.retain(|r| *r != id);
|
||||
self.query_dependents.get_mut(&next_key).unwrap().retain(|r| *r != id);
|
||||
|
||||
// Unblock runtime so that it can resume execution once lock is released:
|
||||
self.unblock_runtime(id, WaitResult::Cycle(cycle));
|
||||
@ -170,10 +152,7 @@ pub(super) fn maybe_unblock_runtimes_in_cycle(
|
||||
key = next_key;
|
||||
}
|
||||
|
||||
let prefix = from_stack
|
||||
.iter()
|
||||
.take_while(|p| p.database_key_index != key)
|
||||
.count();
|
||||
let prefix = from_stack.iter().take_while(|p| p.database_key_index != key).count();
|
||||
let this_unblocked = from_stack[prefix..].iter().any(|aq| aq.cycle.is_some());
|
||||
|
||||
(this_unblocked, others_unblocked)
|
||||
@ -239,10 +218,7 @@ fn add_edge(
|
||||
condvar: condvar.clone(),
|
||||
},
|
||||
);
|
||||
self.query_dependents
|
||||
.entry(database_key)
|
||||
.or_default()
|
||||
.push(from_id);
|
||||
self.query_dependents.entry(database_key).or_default().push(from_id);
|
||||
condvar
|
||||
}
|
||||
|
||||
@ -253,10 +229,7 @@ pub(super) fn unblock_runtimes_blocked_on(
|
||||
database_key: DatabaseKeyIndex,
|
||||
wait_result: WaitResult,
|
||||
) {
|
||||
let dependents = self
|
||||
.query_dependents
|
||||
.remove(&database_key)
|
||||
.unwrap_or_default();
|
||||
let dependents = self.query_dependents.remove(&database_key).unwrap_or_default();
|
||||
|
||||
for from_id in dependents {
|
||||
self.unblock_runtime(from_id, wait_result.clone());
|
||||
|
@ -53,9 +53,7 @@ pub(crate) enum QueryInputs {
|
||||
|
||||
impl Default for LocalState {
|
||||
fn default() -> Self {
|
||||
LocalState {
|
||||
query_stack: RefCell::new(Some(Vec::new())),
|
||||
}
|
||||
LocalState { query_stack: RefCell::new(Some(Vec::new())) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,19 +63,11 @@ pub(super) fn push_query(&self, database_key_index: DatabaseKeyIndex) -> ActiveQ
|
||||
let mut query_stack = self.query_stack.borrow_mut();
|
||||
let query_stack = query_stack.as_mut().expect("local stack taken");
|
||||
query_stack.push(ActiveQuery::new(database_key_index));
|
||||
ActiveQueryGuard {
|
||||
local_state: self,
|
||||
database_key_index,
|
||||
push_len: query_stack.len(),
|
||||
}
|
||||
ActiveQueryGuard { local_state: self, database_key_index, push_len: query_stack.len() }
|
||||
}
|
||||
|
||||
fn with_query_stack<R>(&self, c: impl FnOnce(&mut Vec<ActiveQuery>) -> R) -> R {
|
||||
c(self
|
||||
.query_stack
|
||||
.borrow_mut()
|
||||
.as_mut()
|
||||
.expect("query stack taken"))
|
||||
c(self.query_stack.borrow_mut().as_mut().expect("query stack taken"))
|
||||
}
|
||||
|
||||
pub(super) fn query_in_progress(&self) -> bool {
|
||||
@ -86,9 +76,7 @@ pub(super) fn query_in_progress(&self) -> bool {
|
||||
|
||||
pub(super) fn active_query(&self) -> Option<DatabaseKeyIndex> {
|
||||
self.with_query_stack(|stack| {
|
||||
stack
|
||||
.last()
|
||||
.map(|active_query| active_query.database_key_index)
|
||||
stack.last().map(|active_query| active_query.database_key_index)
|
||||
})
|
||||
}
|
||||
|
||||
@ -156,10 +144,7 @@ pub(super) fn report_synthetic_read(&self, durability: Durability, revision: Rev
|
||||
/// the current thread is blocking. The stack must be restored
|
||||
/// with [`Self::restore_query_stack`] when the thread unblocks.
|
||||
pub(super) fn take_query_stack(&self) -> Vec<ActiveQuery> {
|
||||
assert!(
|
||||
self.query_stack.borrow().is_some(),
|
||||
"query stack already taken"
|
||||
);
|
||||
assert!(self.query_stack.borrow().is_some(), "query stack already taken");
|
||||
self.query_stack.take().unwrap()
|
||||
}
|
||||
|
||||
@ -188,10 +173,7 @@ fn pop_helper(&self) -> ActiveQuery {
|
||||
self.local_state.with_query_stack(|stack| {
|
||||
// Sanity check: pushes and pops should be balanced.
|
||||
assert_eq!(stack.len(), self.push_len);
|
||||
debug_assert_eq!(
|
||||
stack.last().unwrap().database_key_index,
|
||||
self.database_key_index
|
||||
);
|
||||
debug_assert_eq!(stack.last().unwrap().database_key_index, self.database_key_index);
|
||||
stack.pop().unwrap()
|
||||
})
|
||||
}
|
||||
@ -220,8 +202,7 @@ pub(crate) fn pop(self) -> QueryRevisions {
|
||||
/// If the active query is registered as a cycle participant, remove and
|
||||
/// return that cycle.
|
||||
pub(crate) fn take_cycle(&self) -> Option<Cycle> {
|
||||
self.local_state
|
||||
.with_query_stack(|stack| stack.last_mut()?.cycle.take())
|
||||
self.local_state.with_query_stack(|stack| stack.last_mut()?.cycle.take())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,10 +12,7 @@ pub struct Storage<DB: DatabaseStorageTypes> {
|
||||
|
||||
impl<DB: DatabaseStorageTypes> Default for Storage<DB> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
query_store: Default::default(),
|
||||
runtime: Default::default(),
|
||||
}
|
||||
Self { query_store: Default::default(), runtime: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,9 +48,6 @@ pub fn query_store_mut(&mut self) -> (&DB::DatabaseStorage, &mut Runtime) {
|
||||
/// thread. Using two database handles from the **same thread** can lead to
|
||||
/// deadlock.
|
||||
pub fn snapshot(&self) -> Self {
|
||||
Storage {
|
||||
query_store: self.query_store.clone(),
|
||||
runtime: self.runtime.snapshot(),
|
||||
}
|
||||
Storage { query_store: self.query_store.clone(), runtime: self.runtime.snapshot() }
|
||||
}
|
||||
}
|
||||
|
@ -58,17 +58,13 @@ impl salsa::Database for DatabaseImpl {}
|
||||
|
||||
impl ParallelDatabase for DatabaseImpl {
|
||||
fn snapshot(&self) -> Snapshot<Self> {
|
||||
Snapshot::new(DatabaseImpl {
|
||||
storage: self.storage.snapshot(),
|
||||
})
|
||||
Snapshot::new(DatabaseImpl { storage: self.storage.snapshot() })
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for DatabaseImpl {
|
||||
fn default() -> Self {
|
||||
let res = DatabaseImpl {
|
||||
storage: salsa::Storage::default(),
|
||||
};
|
||||
let res = DatabaseImpl { storage: salsa::Storage::default() };
|
||||
|
||||
res
|
||||
}
|
||||
@ -113,15 +109,11 @@ trait Database: salsa::Database {
|
||||
}
|
||||
|
||||
fn recover_a(db: &dyn Database, cycle: &salsa::Cycle) -> Result<(), Error> {
|
||||
Err(Error {
|
||||
cycle: cycle.all_participants(db),
|
||||
})
|
||||
Err(Error { cycle: cycle.all_participants(db) })
|
||||
}
|
||||
|
||||
fn recover_b(db: &dyn Database, cycle: &salsa::Cycle) -> Result<(), Error> {
|
||||
Err(Error {
|
||||
cycle: cycle.all_participants(db),
|
||||
})
|
||||
Err(Error { cycle: cycle.all_participants(db) })
|
||||
}
|
||||
|
||||
fn memoized_a(db: &dyn Database) {
|
||||
|
@ -111,10 +111,7 @@ fn becomes_constant_with_change() {
|
||||
|
||||
db.set_input_with_durability('b', 45, Durability::MEDIUM);
|
||||
assert_eq!(db.add('a', 'b'), 68);
|
||||
assert_eq!(
|
||||
Durability::MEDIUM,
|
||||
AddQuery.in_db(&db).durability(('a', 'b'))
|
||||
);
|
||||
assert_eq!(Durability::MEDIUM, AddQuery.in_db(&db).durability(('a', 'b')));
|
||||
}
|
||||
|
||||
// Test a subtle case in which an input changes from constant to
|
||||
|
@ -12,9 +12,7 @@ impl salsa::Database for Database {}
|
||||
|
||||
impl salsa::ParallelDatabase for Database {
|
||||
fn snapshot(&self) -> salsa::Snapshot<Self> {
|
||||
salsa::Snapshot::new(Database {
|
||||
storage: self.storage.snapshot(),
|
||||
})
|
||||
salsa::Snapshot::new(Database { storage: self.storage.snapshot() })
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,14 +69,8 @@ fn test_intern2() {
|
||||
assert_eq!(bar0, bar1);
|
||||
assert_ne!(foo0, bar0);
|
||||
|
||||
assert_eq!(
|
||||
("x".to_string(), "foo".to_string()),
|
||||
db.lookup_intern2(foo0)
|
||||
);
|
||||
assert_eq!(
|
||||
("x".to_string(), "bar".to_string()),
|
||||
db.lookup_intern2(bar0)
|
||||
);
|
||||
assert_eq!(("x".to_string(), "foo".to_string()), db.lookup_intern2(foo0));
|
||||
assert_eq!(("x".to_string(), "bar".to_string()), db.lookup_intern2(bar0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -16,11 +16,7 @@ trait QueryGroup: salsa::Database + AsRef<HashMap<u32, u32>> {
|
||||
}
|
||||
|
||||
fn a(db: &dyn QueryGroup, x: u32) -> u32 {
|
||||
let durability = if x % 2 == 0 {
|
||||
Durability::LOW
|
||||
} else {
|
||||
Durability::HIGH
|
||||
};
|
||||
let durability = if x % 2 == 0 { Durability::LOW } else { Durability::HIGH };
|
||||
db.salsa_runtime().report_synthetic_read(durability);
|
||||
let external_state: &HashMap<u32, u32> = db.as_ref();
|
||||
external_state[&x]
|
||||
|
@ -33,9 +33,7 @@ impl salsa::Database for DatabaseStruct {}
|
||||
|
||||
impl salsa::ParallelDatabase for DatabaseStruct {
|
||||
fn snapshot(&self) -> Snapshot<Self> {
|
||||
Snapshot::new(DatabaseStruct {
|
||||
storage: self.storage.snapshot(),
|
||||
})
|
||||
Snapshot::new(DatabaseStruct { storage: self.storage.snapshot() })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,11 +37,7 @@ fn parallel_cycle_none_recover() {
|
||||
|
||||
// We expect A to propagate a panic, which causes us to use the sentinel
|
||||
// type `Canceled`.
|
||||
assert!(thread_a
|
||||
.join()
|
||||
.unwrap_err()
|
||||
.downcast_ref::<salsa::Cycle>()
|
||||
.is_some());
|
||||
assert!(thread_a.join().unwrap_err().downcast_ref::<salsa::Cycle>().is_some());
|
||||
}
|
||||
|
||||
#[salsa::query_group(ParallelCycleNoneRecover)]
|
||||
|
@ -38,9 +38,7 @@ impl salsa::Database for StressDatabaseImpl {}
|
||||
|
||||
impl salsa::ParallelDatabase for StressDatabaseImpl {
|
||||
fn snapshot(&self) -> Snapshot<StressDatabaseImpl> {
|
||||
Snapshot::new(StressDatabaseImpl {
|
||||
storage: self.storage.snapshot(),
|
||||
})
|
||||
Snapshot::new(StressDatabaseImpl { storage: self.storage.snapshot() })
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,10 +51,7 @@ enum Query {
|
||||
|
||||
enum MutatorOp {
|
||||
WriteOp(WriteOp),
|
||||
LaunchReader {
|
||||
ops: Vec<ReadOp>,
|
||||
check_cancellation: bool,
|
||||
},
|
||||
LaunchReader { ops: Vec<ReadOp>, check_cancellation: bool },
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -158,13 +153,12 @@ fn stress_test() {
|
||||
for op in write_ops {
|
||||
match op {
|
||||
MutatorOp::WriteOp(w) => w.execute(&mut db),
|
||||
MutatorOp::LaunchReader {
|
||||
ops,
|
||||
check_cancellation,
|
||||
} => all_threads.push(std::thread::spawn({
|
||||
let db = db.snapshot();
|
||||
move || Cancelled::catch(|| db_reader_thread(&db, ops, check_cancellation))
|
||||
})),
|
||||
MutatorOp::LaunchReader { ops, check_cancellation } => {
|
||||
all_threads.push(std::thread::spawn({
|
||||
let db = db.snapshot();
|
||||
move || Cancelled::catch(|| db_reader_thread(&db, ops, check_cancellation))
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,11 +18,10 @@ fn true_parallel_different_keys() {
|
||||
let thread1 = std::thread::spawn({
|
||||
let db = db.snapshot();
|
||||
move || {
|
||||
let v = db.knobs().sum_signal_on_entry.with_value(1, || {
|
||||
db.knobs()
|
||||
.sum_wait_for_on_exit
|
||||
.with_value(2, || db.sum("a"))
|
||||
});
|
||||
let v = db
|
||||
.knobs()
|
||||
.sum_signal_on_entry
|
||||
.with_value(1, || db.knobs().sum_wait_for_on_exit.with_value(2, || db.sum("a")));
|
||||
v
|
||||
}
|
||||
});
|
||||
@ -32,9 +31,10 @@ fn true_parallel_different_keys() {
|
||||
let thread2 = std::thread::spawn({
|
||||
let db = db.snapshot();
|
||||
move || {
|
||||
let v = db.knobs().sum_wait_for_on_entry.with_value(1, || {
|
||||
db.knobs().sum_signal_on_exit.with_value(2, || db.sum("b"))
|
||||
});
|
||||
let v = db
|
||||
.knobs()
|
||||
.sum_wait_for_on_entry
|
||||
.with_value(1, || db.knobs().sum_signal_on_exit.with_value(2, || db.sum("b")));
|
||||
v
|
||||
}
|
||||
});
|
||||
@ -58,11 +58,10 @@ fn true_parallel_same_keys() {
|
||||
let thread1 = std::thread::spawn({
|
||||
let db = db.snapshot();
|
||||
move || {
|
||||
let v = db.knobs().sum_signal_on_entry.with_value(1, || {
|
||||
db.knobs()
|
||||
.sum_wait_for_on_entry
|
||||
.with_value(2, || db.sum("abc"))
|
||||
});
|
||||
let v = db
|
||||
.knobs()
|
||||
.sum_signal_on_entry
|
||||
.with_value(1, || db.knobs().sum_wait_for_on_entry.with_value(2, || db.sum("abc")));
|
||||
v
|
||||
}
|
||||
});
|
||||
@ -99,9 +98,9 @@ fn true_parallel_propagate_panic() {
|
||||
let db = db.snapshot();
|
||||
move || {
|
||||
let v = db.knobs().sum_signal_on_entry.with_value(1, || {
|
||||
db.knobs().sum_wait_for_on_entry.with_value(2, || {
|
||||
db.knobs().sum_should_panic.with_value(true, || db.sum("a"))
|
||||
})
|
||||
db.knobs()
|
||||
.sum_wait_for_on_entry
|
||||
.with_value(2, || db.knobs().sum_should_panic.with_value(true, || db.sum("a")))
|
||||
});
|
||||
v
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user