Fix leak when project is unshared while LSP handler waits for edits

This commit is contained in:
Max Brunsfeld 2023-04-10 16:06:28 -07:00
parent e853e77d59
commit 25e3c4e586
6 changed files with 95 additions and 63 deletions

View file

@ -11,14 +11,14 @@ mod tests;
mod undo_map;
pub use anchor::*;
use anyhow::Result;
use anyhow::{anyhow, Result};
use clock::ReplicaId;
use collections::{HashMap, HashSet};
use fs::LineEnding;
use locator::Locator;
use operation_queue::OperationQueue;
pub use patch::Patch;
use postage::{barrier, oneshot, prelude::*};
use postage::{oneshot, prelude::*};
pub use rope::*;
pub use selection::*;
@ -52,7 +52,7 @@ pub struct Buffer {
pub lamport_clock: clock::Lamport,
subscriptions: Topic,
edit_id_resolvers: HashMap<clock::Local, Vec<oneshot::Sender<()>>>,
version_barriers: Vec<(clock::Global, barrier::Sender)>,
wait_for_version_txs: Vec<(clock::Global, oneshot::Sender<()>)>,
}
#[derive(Clone)]
@ -522,7 +522,7 @@ impl Buffer {
lamport_clock,
subscriptions: Default::default(),
edit_id_resolvers: Default::default(),
version_barriers: Default::default(),
wait_for_version_txs: Default::default(),
}
}
@ -793,8 +793,14 @@ impl Buffer {
}
}
}
self.version_barriers
.retain(|(version, _)| !self.snapshot.version().observed_all(version));
self.wait_for_version_txs.retain_mut(|(version, tx)| {
if self.snapshot.version().observed_all(version) {
tx.try_send(()).ok();
false
} else {
true
}
});
Ok(())
}
@ -1305,7 +1311,7 @@ impl Buffer {
pub fn wait_for_edits(
&mut self,
edit_ids: impl IntoIterator<Item = clock::Local>,
) -> impl 'static + Future<Output = ()> {
) -> impl 'static + Future<Output = Result<()>> {
let mut futures = Vec::new();
for edit_id in edit_ids {
if !self.version.observed(edit_id) {
@ -1317,15 +1323,18 @@ impl Buffer {
async move {
for mut future in futures {
future.recv().await;
if future.recv().await.is_none() {
Err(anyhow!("gave up waiting for edits"))?;
}
}
Ok(())
}
}
pub fn wait_for_anchors<'a>(
&mut self,
anchors: impl IntoIterator<Item = &'a Anchor>,
) -> impl 'static + Future<Output = ()> {
) -> impl 'static + Future<Output = Result<()>> {
let mut futures = Vec::new();
for anchor in anchors {
if !self.version.observed(anchor.timestamp)
@ -1343,21 +1352,36 @@ impl Buffer {
async move {
for mut future in futures {
future.recv().await;
if future.recv().await.is_none() {
Err(anyhow!("gave up waiting for anchors"))?;
}
}
Ok(())
}
}
pub fn wait_for_version(&mut self, version: clock::Global) -> impl Future<Output = ()> {
let (tx, mut rx) = barrier::channel();
pub fn wait_for_version(&mut self, version: clock::Global) -> impl Future<Output = Result<()>> {
let mut rx = None;
if !self.snapshot.version.observed_all(&version) {
self.version_barriers.push((version, tx));
let channel = oneshot::channel();
self.wait_for_version_txs.push((version, channel.0));
rx = Some(channel.1);
}
async move {
rx.recv().await;
if let Some(mut rx) = rx {
if rx.recv().await.is_none() {
Err(anyhow!("gave up waiting for version"))?;
}
}
Ok(())
}
}
pub fn give_up_waiting(&mut self) {
self.edit_id_resolvers.clear();
self.wait_for_version_txs.clear();
}
fn resolve_edit(&mut self, edit_id: clock::Local) {
for mut tx in self
.edit_id_resolvers
@ -1365,7 +1389,7 @@ impl Buffer {
.into_iter()
.flatten()
{
let _ = tx.try_send(());
tx.try_send(()).ok();
}
}
}