Skip to content

Commit

Permalink
fix: dead lock in map (#518)
Browse files Browse the repository at this point in the history
  • Loading branch information
darkskygit committed Aug 22, 2023
1 parent 67d7f25 commit 3adcb89
Showing 1 changed file with 16 additions and 3 deletions.
19 changes: 16 additions & 3 deletions y-octo/src/doc/types/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,18 @@ impl_type!(Map);

pub(crate) trait MapType: AsInner<Inner = YTypeRef> {
fn insert(&mut self, key: impl AsRef<str>, value: impl Into<Content>) -> JwstCodecResult {
let mut inner = self.as_inner().get().unwrap().write().unwrap();
// when we apply update, we may get write store then get ytype, so we ensure
// that everywhere, the write store is fetched before the write ytype to
// avoid deadlocks
let inner = self.as_inner().get().unwrap().read().unwrap();
let left = inner.map.as_ref().and_then(|map| {
map.get(key.as_ref())
.and_then(|struct_info| struct_info.left())
.map(|l| l.as_item())
});
if let Some(store) = inner.store.upgrade() {
drop(inner);

let mut store = store.write().unwrap();
let item = store.create_item(
value.into(),
Expand All @@ -27,6 +32,7 @@ pub(crate) trait MapType: AsInner<Inner = YTypeRef> {
Some(Parent::Type(self.as_inner().clone())),
Some(key.as_ref().into()),
);
let mut inner = self.as_inner().get().unwrap().write().unwrap();
store.integrate(Node::Item(item), 0, Some(&mut inner))?;
}

Expand Down Expand Up @@ -74,12 +80,19 @@ pub(crate) trait MapType: AsInner<Inner = YTypeRef> {
}

fn remove(&mut self, key: impl AsRef<str>) -> bool {
let mut inner = self.as_inner().get().unwrap().write().unwrap();
// when we apply update, we may get write store then get ytype, so we ensure
// that everywhere, the write store is fetched before the write ytype to
// avoid deadlocks
let inner = self.as_inner().get().unwrap().read().unwrap();
let node = inner.map.as_ref().and_then(|map| map.get(key.as_ref()));
if let Some(store) = inner.store.upgrade() {
let mut store = store.write().unwrap();
if let Some(item) = ItemRef::from(node).get() {
drop(inner);

let mut store = store.write().unwrap();
store.delete_set.add(item.id.client, item.id.clock, item.len());

let mut inner = self.as_inner().get().unwrap().write().unwrap();
DocStore::delete_item(item, Some(&mut inner));
return true;
}
Expand Down

0 comments on commit 3adcb89

Please sign in to comment.