Use `try_lock` in `diff_handle` for Diff gutter (#11092)

* Use `try_lock` in `diff_handle` for Diff gutter
- Add the method `try_load() -> Option<Diff>` to `DiffHandle`, using `try_lock` to avoid deadlocks.
- Use said method in `gutter.rs diff()`, which will use a blank `GutterFn` instead when met with a locked `Diff`.

* Revert changes

* Replace `Mutex` with `RwLock` in `Diff`

---------

Co-authored-by: Kaniel Kirby <pirate7007@runbox.com>
pull/11241/merge
kanielrkirby 3 months ago committed by GitHub
parent aaaafb8f5f
commit f0282689da
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -5,7 +5,7 @@ use std::sync::Arc;
use helix_core::Rope; use helix_core::Rope;
use helix_event::RenderLockGuard; use helix_event::RenderLockGuard;
use imara_diff::Algorithm; use imara_diff::Algorithm;
use parking_lot::{Mutex, MutexGuard}; use parking_lot::{RwLock, RwLockReadGuard};
use tokio::sync::mpsc::{unbounded_channel, UnboundedSender}; use tokio::sync::mpsc::{unbounded_channel, UnboundedSender};
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
use tokio::time::Instant; use tokio::time::Instant;
@ -37,7 +37,7 @@ struct DiffInner {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct DiffHandle { pub struct DiffHandle {
channel: UnboundedSender<Event>, channel: UnboundedSender<Event>,
diff: Arc<Mutex<DiffInner>>, diff: Arc<RwLock<DiffInner>>,
inverted: bool, inverted: bool,
} }
@ -48,7 +48,7 @@ impl DiffHandle {
fn new_with_handle(diff_base: Rope, doc: Rope) -> (DiffHandle, JoinHandle<()>) { fn new_with_handle(diff_base: Rope, doc: Rope) -> (DiffHandle, JoinHandle<()>) {
let (sender, receiver) = unbounded_channel(); let (sender, receiver) = unbounded_channel();
let diff: Arc<Mutex<DiffInner>> = Arc::default(); let diff: Arc<RwLock<DiffInner>> = Arc::default();
let worker = DiffWorker { let worker = DiffWorker {
channel: receiver, channel: receiver,
diff: diff.clone(), diff: diff.clone(),
@ -70,7 +70,7 @@ impl DiffHandle {
pub fn load(&self) -> Diff { pub fn load(&self) -> Diff {
Diff { Diff {
diff: self.diff.lock(), diff: self.diff.read(),
inverted: self.inverted, inverted: self.inverted,
} }
} }
@ -164,7 +164,7 @@ impl Hunk {
/// non-overlapping order /// non-overlapping order
#[derive(Debug)] #[derive(Debug)]
pub struct Diff<'a> { pub struct Diff<'a> {
diff: MutexGuard<'a, DiffInner>, diff: RwLockReadGuard<'a, DiffInner>,
inverted: bool, inverted: bool,
} }

@ -4,7 +4,7 @@ use std::sync::Arc;
use helix_core::{Rope, RopeSlice}; use helix_core::{Rope, RopeSlice};
use imara_diff::intern::InternedInput; use imara_diff::intern::InternedInput;
use parking_lot::Mutex; use parking_lot::RwLock;
use tokio::sync::mpsc::UnboundedReceiver; use tokio::sync::mpsc::UnboundedReceiver;
use tokio::sync::Notify; use tokio::sync::Notify;
use tokio::time::{timeout, timeout_at, Duration}; use tokio::time::{timeout, timeout_at, Duration};
@ -21,7 +21,7 @@ mod test;
pub(super) struct DiffWorker { pub(super) struct DiffWorker {
pub channel: UnboundedReceiver<Event>, pub channel: UnboundedReceiver<Event>,
pub diff: Arc<Mutex<DiffInner>>, pub diff: Arc<RwLock<DiffInner>>,
pub new_hunks: Vec<Hunk>, pub new_hunks: Vec<Hunk>,
pub diff_finished_notify: Arc<Notify>, pub diff_finished_notify: Arc<Notify>,
} }
@ -73,7 +73,7 @@ impl DiffWorker {
/// `self.new_hunks` is always empty after this function runs. /// `self.new_hunks` is always empty after this function runs.
/// To improve performance this function tries to reuse the allocation of the old diff previously stored in `self.line_diffs` /// To improve performance this function tries to reuse the allocation of the old diff previously stored in `self.line_diffs`
fn apply_hunks(&mut self, diff_base: Rope, doc: Rope) { fn apply_hunks(&mut self, diff_base: Rope, doc: Rope) {
let mut diff = self.diff.lock(); let mut diff = self.diff.write();
diff.diff_base = diff_base; diff.diff_base = diff_base;
diff.doc = doc; diff.doc = doc;
swap(&mut diff.hunks, &mut self.new_hunks); swap(&mut diff.hunks, &mut self.new_hunks);

@ -12,7 +12,7 @@ impl DiffHandle {
// dropping the channel terminates the task // dropping the channel terminates the task
drop(self.channel); drop(self.channel);
handle.await.unwrap(); handle.await.unwrap();
let diff = diff.lock(); let diff = diff.read();
Vec::clone(&diff.hunks) Vec::clone(&diff.hunks)
} }
} }

Loading…
Cancel
Save