aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_db/src/cancelation.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-12-27 09:59:30 +0000
committerAleksey Kladov <[email protected]>2018-12-27 10:03:32 +0000
commit93996fecdc6866412fa51120ba33150c4107d42e (patch)
tree9786b92d05c2c2dd7390344331209d55e36ed549 /crates/ra_db/src/cancelation.rs
parent62c40b0e91e79094daf7491526aa8b164a7d198c (diff)
add cancelation module & cancelation backtraces
Diffstat (limited to 'crates/ra_db/src/cancelation.rs')
-rw-r--r--crates/ra_db/src/cancelation.rs85
1 files changed, 85 insertions, 0 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}