mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-23 13:10:19 +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::QueryStorageOps;
|
||||||
use crate::UncheckedMutQueryStorageOps;
|
use crate::UncheckedMutQueryStorageOps;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
use parking_lot::Condvar;
|
||||||
|
use parking_lot::Mutex;
|
||||||
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
|
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
@ -41,6 +43,18 @@ where
|
||||||
{
|
{
|
||||||
map: RwLock<FxHashMap<Q::Key, QueryState<DB, Q>>>,
|
map: RwLock<FxHashMap<Q::Key, QueryState<DB, Q>>>,
|
||||||
policy: PhantomData<MP>,
|
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>
|
pub trait MemoizationPolicy<DB, Q>
|
||||||
|
@ -151,6 +165,8 @@ where
|
||||||
DerivedStorage {
|
DerivedStorage {
|
||||||
map: RwLock::new(FxHashMap::default()),
|
map: RwLock::new(FxHashMap::default()),
|
||||||
policy: PhantomData,
|
policy: PhantomData,
|
||||||
|
signal_cond_var: Default::default(),
|
||||||
|
signal_mutex: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -332,6 +348,49 @@ where
|
||||||
Err(map)
|
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(
|
fn overwrite_placeholder(
|
||||||
&self,
|
&self,
|
||||||
runtime: &Runtime<DB>,
|
runtime: &Runtime<DB>,
|
||||||
|
|
Loading…
Reference in a new issue