mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-23 05:07:27 +00:00
[WIP] await_other_guard fn
This commit is contained in:
parent
00c76be635
commit
ea0b196a5d
1 changed files with 59 additions and 0 deletions
|
@ -11,6 +11,8 @@ use crate::QueryFunction;
|
|||
use crate::QueryStorageOps;
|
||||
use crate::UncheckedMutQueryStorageOps;
|
||||
use log::debug;
|
||||
use parking_lot::Condvar;
|
||||
use parking_lot::Mutex;
|
||||
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
|
||||
use rustc_hash::FxHashMap;
|
||||
use std::marker::PhantomData;
|
||||
|
@ -41,6 +43,18 @@ where
|
|||
{
|
||||
map: RwLock<FxHashMap<Q::Key, QueryState<DB, Q>>>,
|
||||
policy: PhantomData<MP>,
|
||||
|
||||
/// This cond var is used when one thread is waiting on another to
|
||||
/// produce some specific key. In that case, the thread producing
|
||||
/// the key will signal the cond-var. The threads awaiting the key
|
||||
/// will check in `map` to see if their key is present and (if
|
||||
/// not) await the cond-var.
|
||||
signal_cond_var: Condvar,
|
||||
|
||||
/// Mutex used for `signal_cond_var`. Note that this mutex is
|
||||
/// never acquired while holding the lock on `map` (but you may
|
||||
/// acquire the `map` lock while holding this mutex).
|
||||
signal_mutex: Mutex<()>,
|
||||
}
|
||||
|
||||
pub trait MemoizationPolicy<DB, Q>
|
||||
|
@ -151,6 +165,8 @@ where
|
|||
DerivedStorage {
|
||||
map: RwLock::new(FxHashMap::default()),
|
||||
policy: PhantomData,
|
||||
signal_cond_var: Default::default(),
|
||||
signal_mutex: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -332,6 +348,49 @@ where
|
|||
Err(map)
|
||||
}
|
||||
|
||||
/// If some other thread is tasked with producing a memoized
|
||||
/// result for this value, then wait for them.
|
||||
///
|
||||
/// Pre-conditions:
|
||||
/// - we have installed ourselves in the dependency graph and set the
|
||||
/// bool that informs the producer we are waiting
|
||||
/// - `self.map` must be locked (with `map_guard` as the guard)
|
||||
fn await_other_thread<MapGuard>(
|
||||
&self,
|
||||
map_guard: MapGuard,
|
||||
revision_now: Revision,
|
||||
key: &Q::Key,
|
||||
) -> StampedValue<Q::Value>
|
||||
where
|
||||
MapGuard: Deref<Target = FxHashMap<Q::Key, QueryState<DB, Q>>>,
|
||||
{
|
||||
// Intentionally release the lock on map. We cannot be holding
|
||||
// it while we are sleeping!
|
||||
std::mem::drop(map_guard);
|
||||
|
||||
let mut signal_lock_guard = self.signal_mutex.lock();
|
||||
|
||||
loop {
|
||||
{
|
||||
let map = self.map.read();
|
||||
|
||||
if let Some(QueryState::Memoized(m)) = map.get(key) {
|
||||
assert_eq!(m.verified_at, revision_now);
|
||||
return if let Some(value) = &m.value {
|
||||
StampedValue {
|
||||
value: value.clone(),
|
||||
changed_at: m.changed_at,
|
||||
}
|
||||
} else {
|
||||
panic!("awaiting production of non-memoized value");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
self.signal_cond_var.wait(&mut signal_lock_guard);
|
||||
}
|
||||
}
|
||||
|
||||
fn overwrite_placeholder(
|
||||
&self,
|
||||
runtime: &Runtime<DB>,
|
||||
|
|
Loading…
Reference in a new issue