]> git.lizzy.rs Git - rust.git/commitdiff
add cancelation module & cancelation backtraces
authorAleksey Kladov <aleksey.kladov@gmail.com>
Thu, 27 Dec 2018 09:59:30 +0000 (12:59 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Thu, 27 Dec 2018 10:03:32 +0000 (13:03 +0300)
Cargo.lock
crates/ra_db/Cargo.toml
crates/ra_db/src/cancelation.rs [new file with mode: 0644]
crates/ra_db/src/lib.rs
crates/ra_lsp_server/src/main_loop.rs

index 51cf1825d6bf8cac7a12e0005257abb1334bcdd9..69134b434b0fc9d4e570c4891f459f9b96707b1e 100644 (file)
@@ -668,6 +668,7 @@ dependencies = [
 name = "ra_db"
 version = "0.1.0"
 dependencies = [
+ "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "ra_editor 0.1.0",
  "ra_syntax 0.1.0",
index f316c0ab2f371270aa49be2b983c7ce202345778..4be32b5f314abce73b60e3f360163a184ac0273d 100644 (file)
@@ -5,6 +5,7 @@ version = "0.1.0"
 authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
 
 [dependencies]
+backtrace = "0.3.1"
 relative-path = "0.4.0"
 salsa = "0.8.0"
 rustc-hash = "1.0"
diff --git a/crates/ra_db/src/cancelation.rs b/crates/ra_db/src/cancelation.rs
new file mode 100644 (file)
index 0000000..73444b0
--- /dev/null
@@ -0,0 +1,85 @@
+//! Utility types to support cancellation.
+//!
+//! In a typical IDE use-case, requests and modification happen concurrently, as
+//! in the following scenario:
+//!
+//!   * user types a character,
+//!   * a syntax highlighting process is started
+//!   * user types next character, while syntax highlighting *is still in
+//!     progress*.
+//!
+//! In this situation, we want to react to modification as quckly as possible.
+//! At the same time, in-progress results are not very interesting, because they
+//! are invalidated by the edit anyway. So, we first cancel all in-flight
+//! requests, and then apply modification knowing that it won't intrfere with
+//! any background processing (this bit is handled by salsa, see
+//! `BaseDatabase::check_canceled` method).
+
+use std::{
+    cmp,
+    hash::{Hash, Hasher},
+    sync::Arc,
+};
+
+use backtrace::Backtrace;
+use parking_lot::Mutex;
+
+/// An "error" signifing that the operation was canceled.
+#[derive(Clone)]
+pub struct Canceled {
+    backtrace: Arc<Mutex<Backtrace>>,
+}
+
+pub type Cancelable<T> = Result<T, Canceled>;
+
+impl Canceled {
+    pub(crate) fn new() -> Canceled {
+        let bt = Backtrace::new_unresolved();
+        Canceled {
+            backtrace: Arc::new(Mutex::new(bt)),
+        }
+    }
+}
+
+impl std::fmt::Display for Canceled {
+    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        fmt.write_str("canceled")
+    }
+}
+
+impl std::fmt::Debug for Canceled {
+    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let mut bt = self.backtrace.lock();
+        let bt: &mut Backtrace = &mut *bt;
+        bt.resolve();
+        write!(fmt, "canceled at:\n{:?}", bt)
+    }
+}
+
+impl std::error::Error for Canceled {}
+
+impl PartialEq for Canceled {
+    fn eq(&self, _: &Canceled) -> bool {
+        true
+    }
+}
+
+impl Eq for Canceled {}
+
+impl Hash for Canceled {
+    fn hash<H: Hasher>(&self, hasher: &mut H) {
+        ().hash(hasher)
+    }
+}
+
+impl cmp::Ord for Canceled {
+    fn cmp(&self, _: &Canceled) -> cmp::Ordering {
+        cmp::Ordering::Equal
+    }
+}
+
+impl cmp::PartialOrd for Canceled {
+    fn partial_cmp(&self, other: &Canceled) -> Option<cmp::Ordering> {
+        Some(self.cmp(other))
+    }
+}
index 78f2cbf12b02e061dc65aa32f9f0d991b59a47d3..1f7c9187be7de2667920d0c1603594fd1b446d72 100644 (file)
@@ -1,27 +1,17 @@
 //! ra_db defines basic database traits. Concrete DB is defined by ra_analysis.
+mod cancelation;
 mod syntax_ptr;
 mod input;
 mod loc2id;
 pub mod mock;
 
 use std::sync::Arc;
+
 use ra_editor::LineIndex;
 use ra_syntax::{TextUnit, SourceFileNode};
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub struct Canceled;
-
-pub type Cancelable<T> = Result<T, Canceled>;
-
-impl std::fmt::Display for Canceled {
-    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        fmt.write_str("canceled")
-    }
-}
-
-impl std::error::Error for Canceled {}
-
 pub use crate::{
+    cancelation::{Canceled, Cancelable},
     syntax_ptr::LocalSyntaxPtr,
     input::{
         FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph,
@@ -48,7 +38,7 @@ fn to_u32(self) -> u32 {
 pub trait BaseDatabase: salsa::Database {
     fn check_canceled(&self) -> Cancelable<()> {
         if self.salsa_runtime().is_current_revision_canceled() {
-            Err(Canceled)
+            Err(Canceled::new())
         } else {
             Ok(())
         }
index 60f13267c2931bb789f9f450718ebdda254de9e9..1edb9fae4956df0558565c46c9c8e679a286dd60 100644 (file)
@@ -427,7 +427,7 @@ fn on<'b, R>(
                                     RawResponse::err(
                                         id,
                                         ErrorCode::ContentModified as i32,
-                                        format!("content modified: {}", e),
+                                        format!("content modified: {:?}", e),
                                     )
                                 } else {
                                     RawResponse::err(