mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-13 00:40:22 +00:00
merge read_probe
and probe
This commit is contained in:
parent
be983aacdf
commit
a8fd113636
1 changed files with 34 additions and 72 deletions
106
src/derived.rs
106
src/derived.rs
|
@ -207,7 +207,7 @@ where
|
|||
);
|
||||
|
||||
// First, do a check with a read-lock.
|
||||
match self.read_probe(self.map.read(), runtime, revision_now, descriptor, key) {
|
||||
match self.probe(self.map.read(), runtime, revision_now, descriptor, key) {
|
||||
ProbeState::UpToDate(v) => return Ok(v),
|
||||
ProbeState::CycleDetected => return Err(CycleDetected),
|
||||
ProbeState::StaleOrAbsent(_guard) => (),
|
||||
|
@ -232,7 +232,7 @@ where
|
|||
// Check with an upgradable read to see if there is a value
|
||||
// already. (This permits other readers but prevents anyone
|
||||
// else from running `read_upgrade` at the same time.)
|
||||
let mut old_value = match self.read_probe(
|
||||
let mut old_value = match self.probe(
|
||||
self.map.upgradable_read(),
|
||||
runtime,
|
||||
revision_now,
|
||||
|
@ -329,13 +329,25 @@ where
|
|||
|
||||
/// Helper for `read`:
|
||||
///
|
||||
/// Looks in the map to see if we have an up-to-date value or a
|
||||
/// cycle. If so, returns `Ok(v)` with either the value or a cycle-error;
|
||||
/// this can be propagated as the final result of read.
|
||||
/// Invoked with the guard `map` of some lock on `self.map` (read
|
||||
/// or write) as well as details about the key to look up. Looks
|
||||
/// in the map to see if we have an up-to-date value or a
|
||||
/// cycle. Returns a suitable `ProbeState`:
|
||||
///
|
||||
/// Otherwise, returns `Err(map)` where `map` is the lock guard
|
||||
/// that was given in as argument.
|
||||
fn read_probe<MapGuard>(
|
||||
/// - `ProbeState::UpToDate(r)` if the table has an up-to-date
|
||||
/// value (or we blocked on another thread that produced such a value).
|
||||
/// - `ProbeState::CycleDetected` if this thread is (directly or
|
||||
/// indirectly) already computing this value.
|
||||
/// - `ProbeState::BlockedOnOtherThread` if some other thread
|
||||
/// (which does not depend on us) was already computing this
|
||||
/// value; caller should re-acquire the lock and try again.
|
||||
/// - `ProbeState::StaleOrAbsent` if either (a) there is no memo
|
||||
/// for this key, (b) the memo has no value; or (c) the memo
|
||||
/// has not been verified at the current revision.
|
||||
///
|
||||
/// Note that in all cases **except** for `StaleOrAbsent`, the lock on
|
||||
/// `map` will have been released.
|
||||
fn probe<MapGuard>(
|
||||
&self,
|
||||
map: MapGuard,
|
||||
runtime: &Runtime<DB>,
|
||||
|
@ -343,64 +355,6 @@ where
|
|||
descriptor: &DB::QueryDescriptor,
|
||||
key: &Q::Key,
|
||||
) -> ProbeState<StampedValue<Q::Value>, MapGuard>
|
||||
where
|
||||
MapGuard: Deref<Target = FxHashMap<Q::Key, QueryState<DB, Q>>>,
|
||||
{
|
||||
self.probe(
|
||||
map,
|
||||
runtime,
|
||||
revision_now,
|
||||
descriptor,
|
||||
key,
|
||||
|memo| {
|
||||
if let Some(value) = &memo.value {
|
||||
debug!(
|
||||
"{:?}({:?}): returning memoized value (changed_at={:?})",
|
||||
Q::default(),
|
||||
key,
|
||||
memo.changed_at,
|
||||
);
|
||||
Some(StampedValue {
|
||||
value: value.clone(),
|
||||
changed_at: memo.changed_at,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
|v| v,
|
||||
)
|
||||
}
|
||||
|
||||
/// Helper:
|
||||
///
|
||||
/// Invoked with the guard `map` of some lock on `self.map` (read
|
||||
/// or write) as well as details about the key to look up. It will
|
||||
/// check the map and return a suitable `ProbeState`:
|
||||
///
|
||||
/// - `ProbeState::UpToDate(r)` if the memo is up-to-date,
|
||||
/// and invoking `with_up_to_date_memo` returned `Some(r)`.
|
||||
/// - `ProbeState::CycleDetected` if this thread is (directly or
|
||||
/// indirectly) already computing this value.
|
||||
/// - `ProbeState::BlockedOnOtherThread` if some other thread
|
||||
/// (which does not depend on us) was already computing this
|
||||
/// value; caller should re-acquire the lock and try again.
|
||||
/// - `ProbeState::StaleOrAbsent` if either (a) there is no memo for this key,
|
||||
/// (b) the memo has not been verified at the current revision, or
|
||||
/// (c) `with_up_to_date_memo` returned `None`.
|
||||
///
|
||||
/// Note that in all cases **except** for `StaleOrAbsent`, the lock on
|
||||
/// `map` will have been released.
|
||||
fn probe<MapGuard, R>(
|
||||
&self,
|
||||
map: MapGuard,
|
||||
runtime: &Runtime<DB>,
|
||||
revision_now: Revision,
|
||||
descriptor: &DB::QueryDescriptor,
|
||||
key: &Q::Key,
|
||||
with_up_to_date_memo: impl FnOnce(&Memo<DB, Q>) -> Option<R>,
|
||||
with_stamped_value: impl FnOnce(StampedValue<Q::Value>) -> R,
|
||||
) -> ProbeState<R, MapGuard>
|
||||
where
|
||||
MapGuard: Deref<Target = FxHashMap<Q::Key, QueryState<DB, Q>>>,
|
||||
{
|
||||
|
@ -425,25 +379,33 @@ where
|
|||
std::mem::drop(map);
|
||||
|
||||
let value = rx.recv().unwrap();
|
||||
let value = with_stamped_value(value);
|
||||
return ProbeState::UpToDate(value);
|
||||
}
|
||||
}
|
||||
|
||||
Some(QueryState::Memoized(m)) => {
|
||||
Some(QueryState::Memoized(memo)) => {
|
||||
debug!(
|
||||
"{:?}({:?}): found memoized value verified_at={:?}",
|
||||
Q::default(),
|
||||
key,
|
||||
m.verified_at,
|
||||
memo.verified_at,
|
||||
);
|
||||
|
||||
// We've found that the query is definitely up-to-date.
|
||||
// If the value is also memoized, return it.
|
||||
// Otherwise fallback to recomputing the value.
|
||||
if m.verified_at == revision_now {
|
||||
if let Some(r) = with_up_to_date_memo(&m) {
|
||||
return ProbeState::UpToDate(r);
|
||||
if memo.verified_at == revision_now {
|
||||
if let Some(value) = &memo.value {
|
||||
debug!(
|
||||
"{:?}({:?}): returning memoized value (changed_at={:?})",
|
||||
Q::default(),
|
||||
key,
|
||||
memo.changed_at,
|
||||
);
|
||||
return ProbeState::UpToDate(StampedValue {
|
||||
value: value.clone(),
|
||||
changed_at: memo.changed_at,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue