Refactor out some illegal states

It's impossible to have an `InProgress` state here, so let's ensure
that!
This commit is contained in:
Aleksey Kladov 2018-10-16 12:48:01 +03:00
parent a128861a2c
commit 5abd02097d

View file

@ -230,7 +230,7 @@ where
// Check with an upgradable read to see if there is a value // Check with an upgradable read to see if there is a value
// already. (This permits other readers but prevents anyone // already. (This permits other readers but prevents anyone
// else from running `read_upgrade` at the same time.) // else from running `read_upgrade` at the same time.)
let mut old_value = match self.probe( let mut old_memo = match self.probe(
self.map.upgradable_read(), self.map.upgradable_read(),
runtime, runtime,
revision_now, revision_now,
@ -240,7 +240,11 @@ where
ProbeState::UpToDate(v) => return v, ProbeState::UpToDate(v) => return v,
ProbeState::StaleOrAbsent(map) => { ProbeState::StaleOrAbsent(map) => {
let mut map = RwLockUpgradableReadGuard::upgrade(map); let mut map = RwLockUpgradableReadGuard::upgrade(map);
map.insert(key.clone(), QueryState::in_progress(runtime.id())) match map.insert(key.clone(), QueryState::in_progress(runtime.id())) {
Some(QueryState::Memoized(old_memo)) => Some(old_memo),
Some(QueryState::InProgress { .. }) => unreachable!(),
None => None
}
} }
}; };
@ -248,21 +252,21 @@ where
// has been a new revision since the last time we checked. So, // has been a new revision since the last time we checked. So,
// first things first, let's walk over each of our previous // first things first, let's walk over each of our previous
// inputs and check whether they are out of date. // inputs and check whether they are out of date.
if let Some(QueryState::Memoized(old_memo)) = &mut old_value { if let Some(memo) = &mut old_memo {
if let Some(value) = old_memo.verify_memoized_value(db) { if let Some(value) = memo.verify_memoized_value(db) {
debug!("{:?}({:?}): inputs still valid", Q::default(), key); debug!("{:?}({:?}): inputs still valid", Q::default(), key);
// If none of out inputs have changed since the last time we refreshed // If none of out inputs have changed since the last time we refreshed
// our value, then our value must still be good. We'll just patch // our value, then our value must still be good. We'll just patch
// the verified-at date and re-use it. // the verified-at date and re-use it.
old_memo.verified_at = revision_now; memo.verified_at = revision_now;
let changed_at = old_memo.changed_at; let changed_at = memo.changed_at;
let new_value = StampedValue { value, changed_at }; let new_value = StampedValue { value, changed_at };
self.overwrite_placeholder( self.overwrite_placeholder(
runtime, runtime,
descriptor, descriptor,
key, key,
old_value.unwrap(), old_memo.unwrap(),
&new_value, &new_value,
); );
return Ok(new_value); return Ok(new_value);
@ -294,7 +298,7 @@ where
// really change, even if some of its inputs have. So we can // really change, even if some of its inputs have. So we can
// "backdate" its `changed_at` revision to be the same as the // "backdate" its `changed_at` revision to be the same as the
// old value. // old value.
if let Some(QueryState::Memoized(old_memo)) = &old_value { if let Some(old_memo) = &old_memo {
if old_memo.value.as_ref() == Some(&stamped_value.value) { if old_memo.value.as_ref() == Some(&stamped_value.value) {
assert!(old_memo.changed_at <= stamped_value.changed_at); assert!(old_memo.changed_at <= stamped_value.changed_at);
stamped_value.changed_at = old_memo.changed_at; stamped_value.changed_at = old_memo.changed_at;
@ -311,12 +315,12 @@ where
runtime, runtime,
descriptor, descriptor,
key, key,
QueryState::Memoized(Memo { Memo {
changed_at: stamped_value.changed_at, changed_at: stamped_value.changed_at,
value, value,
inputs, inputs,
verified_at: revision_now, verified_at: revision_now,
}), },
&stamped_value, &stamped_value,
); );
} }
@ -446,13 +450,13 @@ where
runtime: &Runtime<DB>, runtime: &Runtime<DB>,
descriptor: &DB::QueryDescriptor, descriptor: &DB::QueryDescriptor,
key: &Q::Key, key: &Q::Key,
map_value: QueryState<DB, Q>, memo: Memo<DB, Q>,
new_value: &StampedValue<Q::Value>, new_value: &StampedValue<Q::Value>,
) { ) {
// Overwrite the value, releasing the lock afterwards: // Overwrite the value, releasing the lock afterwards:
let waiting = { let waiting = {
let mut write = self.map.write(); let mut write = self.map.write();
match write.insert(key.clone(), map_value) { match write.insert(key.clone(), QueryState::Memoized(memo)) {
Some(QueryState::InProgress { id, waiting }) => { Some(QueryState::InProgress { id, waiting }) => {
assert_eq!(id, runtime.id()); assert_eq!(id, runtime.id());