aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_db/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_db/src')
-rw-r--r--crates/ra_db/src/cancelation.rs85
-rw-r--r--crates/ra_db/src/lib.rs18
2 files changed, 89 insertions, 14 deletions
diff --git a/crates/ra_db/src/cancelation.rs b/crates/ra_db/src/cancelation.rs
new file mode 100644
index 000000000..73444b015
--- /dev/null
+++ b/crates/ra_db/src/cancelation.rs
@@ -0,0 +1,85 @@
1//! Utility types to support cancellation.
2//!
3//! In a typical IDE use-case, requests and modification happen concurrently, as
4//! in the following scenario:
5//!
6//! * user types a character,
7//! * a syntax highlighting process is started
8//! * user types next character, while syntax highlighting *is still in
9//! progress*.
10//!
11//! In this situation, we want to react to modification as quckly as possible.
12//! At the same time, in-progress results are not very interesting, because they
13//! are invalidated by the edit anyway. So, we first cancel all in-flight
14//! requests, and then apply modification knowing that it won't intrfere with
15//! any background processing (this bit is handled by salsa, see
16//! `BaseDatabase::check_canceled` method).
17
18use std::{
19 cmp,
20 hash::{Hash, Hasher},
21 sync::Arc,
22};
23
24use backtrace::Backtrace;
25use parking_lot::Mutex;
26
27/// An "error" signifing that the operation was canceled.
28#[derive(Clone)]
29pub struct Canceled {
30 backtrace: Arc<Mutex<Backtrace>>,
31}
32
33pub type Cancelable<T> = Result<T, Canceled>;
34
35impl Canceled {
36 pub(crate) fn new() -> Canceled {
37 let bt = Backtrace::new_unresolved();
38 Canceled {
39 backtrace: Arc::new(Mutex::new(bt)),
40 }
41 }
42}
43
44impl std::fmt::Display for Canceled {
45 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 fmt.write_str("canceled")
47 }
48}
49
50impl std::fmt::Debug for Canceled {
51 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 let mut bt = self.backtrace.lock();
53 let bt: &mut Backtrace = &mut *bt;
54 bt.resolve();
55 write!(fmt, "canceled at:\n{:?}", bt)
56 }
57}
58
59impl std::error::Error for Canceled {}
60
61impl PartialEq for Canceled {
62 fn eq(&self, _: &Canceled) -> bool {
63 true
64 }
65}
66
67impl Eq for Canceled {}
68
69impl Hash for Canceled {
70 fn hash<H: Hasher>(&self, hasher: &mut H) {
71 ().hash(hasher)
72 }
73}
74
75impl cmp::Ord for Canceled {
76 fn cmp(&self, _: &Canceled) -> cmp::Ordering {
77 cmp::Ordering::Equal
78 }
79}
80
81impl cmp::PartialOrd for Canceled {
82 fn partial_cmp(&self, other: &Canceled) -> Option<cmp::Ordering> {
83 Some(self.cmp(other))
84 }
85}
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index 78f2cbf12..1f7c9187b 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -1,27 +1,17 @@
1//! ra_db defines basic database traits. Concrete DB is defined by ra_analysis. 1//! ra_db defines basic database traits. Concrete DB is defined by ra_analysis.
2mod cancelation;
2mod syntax_ptr; 3mod syntax_ptr;
3mod input; 4mod input;
4mod loc2id; 5mod loc2id;
5pub mod mock; 6pub mod mock;
6 7
7use std::sync::Arc; 8use std::sync::Arc;
9
8use ra_editor::LineIndex; 10use ra_editor::LineIndex;
9use ra_syntax::{TextUnit, SourceFileNode}; 11use ra_syntax::{TextUnit, SourceFileNode};
10 12
11#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
12pub struct Canceled;
13
14pub type Cancelable<T> = Result<T, Canceled>;
15
16impl std::fmt::Display for Canceled {
17 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 fmt.write_str("canceled")
19 }
20}
21
22impl std::error::Error for Canceled {}
23
24pub use crate::{ 13pub use crate::{
14 cancelation::{Canceled, Cancelable},
25 syntax_ptr::LocalSyntaxPtr, 15 syntax_ptr::LocalSyntaxPtr,
26 input::{ 16 input::{
27 FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, 17 FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph,
@@ -48,7 +38,7 @@ macro_rules! impl_numeric_id {
48pub trait BaseDatabase: salsa::Database { 38pub trait BaseDatabase: salsa::Database {
49 fn check_canceled(&self) -> Cancelable<()> { 39 fn check_canceled(&self) -> Cancelable<()> {
50 if self.salsa_runtime().is_current_revision_canceled() { 40 if self.salsa_runtime().is_current_revision_canceled() {
51 Err(Canceled) 41 Err(Canceled::new())
52 } else { 42 } else {
53 Ok(()) 43 Ok(())
54 } 44 }