diff --git a/src/buffer/controller.rs b/src/buffer/controller.rs index e14c9e7..1d33f9d 100644 --- a/src/buffer/controller.rs +++ b/src/buffer/controller.rs @@ -49,8 +49,8 @@ impl BufferController { BufferController { name, content, operations, poller, - _stop: Arc::new(StopOnDrop(stop)), seen: Arc::new(RwLock::new("".into())), + _stop: Arc::new(StopOnDrop(stop)), } } @@ -72,12 +72,14 @@ impl Drop for StopOnDrop { impl Controller for BufferController { type Input = TextChange; + // block until a new text change is available async fn poll(&self) -> crate::Result<()> { let (tx, rx) = oneshot::channel::<()>(); self.poller.send(tx).await?; Ok(rx.await.map_err(|_| crate::Error::Channel { send: false })?) } + // if a new text change is available, return it immediately fn try_recv(&self) -> crate::Result> { let seen = match self.seen.try_read() { Err(_) => return Err(crate::Error::Deadlocked), @@ -95,6 +97,7 @@ impl Controller for BufferController { Ok(Some(change)) } + // block until a new text change is available, and return it async fn recv(&self) -> crate::Result { self.poll().await?; let cur = self.seen.read().await.clone(); diff --git a/src/client.rs b/src/client.rs index ec8adda..3745723 100644 --- a/src/client.rs +++ b/src/client.rs @@ -152,6 +152,14 @@ impl Client { } + /// invoke .poll() on all buffer controllers and wait, return name of first one ready + /// + /// this will spawn tasks for each buffer controller, each blocked in a poll() call. as soon as + /// one finishes, all other tasks will be canceled and the name of ready controller will be + /// returned. just do client.get_buffer(name).try_recv() + /// + /// this is not super efficient as of now but has room for improvement. using this API may + /// provide significant improvements on editor-side pub async fn select_buffer(&self) -> crate::Result { match &self.workspace { None => Err(Error::InvalidState { msg: "join workspace first".into() }),