diff options
author | Aleksey Kladov <[email protected]> | 2019-08-30 18:23:28 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-08-30 18:32:59 +0100 |
commit | 983de30a567f2cb4d9e28e12702e509ca713da62 (patch) | |
tree | 9bdd597701e1b150492a78b6c85ff856f0fc51bd /crates/ra_lsp_server/src | |
parent | 7cc14a759699dd2503199116521e9ba65e3f1aa8 (diff) |
inline thread-worker
Diffstat (limited to 'crates/ra_lsp_server/src')
-rw-r--r-- | crates/ra_lsp_server/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/project_model.rs | 4 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/thread_worker.rs | 49 |
3 files changed, 51 insertions, 3 deletions
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs index 2c5d7c72d..69a577b3e 100644 --- a/crates/ra_lsp_server/src/lib.rs +++ b/crates/ra_lsp_server/src/lib.rs | |||
@@ -8,6 +8,7 @@ mod project_model; | |||
8 | pub mod req; | 8 | pub mod req; |
9 | pub mod config; | 9 | pub mod config; |
10 | mod world; | 10 | mod world; |
11 | mod thread_worker; | ||
11 | 12 | ||
12 | pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>; | 13 | pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>; |
13 | pub use crate::{ | 14 | pub use crate::{ |
diff --git a/crates/ra_lsp_server/src/project_model.rs b/crates/ra_lsp_server/src/project_model.rs index ad59cde64..6234563f2 100644 --- a/crates/ra_lsp_server/src/project_model.rs +++ b/crates/ra_lsp_server/src/project_model.rs | |||
@@ -1,8 +1,6 @@ | |||
1 | use std::path::PathBuf; | 1 | use std::path::PathBuf; |
2 | 2 | ||
3 | use thread_worker::Worker; | 3 | use crate::{thread_worker::Worker, Result}; |
4 | |||
5 | use crate::Result; | ||
6 | 4 | ||
7 | pub use ra_project_model::{ | 5 | pub use ra_project_model::{ |
8 | CargoWorkspace, Package, ProjectWorkspace, Sysroot, Target, TargetKind, | 6 | CargoWorkspace, Package, ProjectWorkspace, Sysroot, Target, TargetKind, |
diff --git a/crates/ra_lsp_server/src/thread_worker.rs b/crates/ra_lsp_server/src/thread_worker.rs new file mode 100644 index 000000000..68e5c124d --- /dev/null +++ b/crates/ra_lsp_server/src/thread_worker.rs | |||
@@ -0,0 +1,49 @@ | |||
1 | //! Small utility to correctly spawn crossbeam-channel based worker threads. | ||
2 | |||
3 | use crossbeam_channel::{bounded, unbounded, Receiver, Sender}; | ||
4 | |||
5 | /// A wrapper around event-processing thread with automatic shutdown semantics. | ||
6 | pub struct Worker<I, O> { | ||
7 | // XXX: field order is significant here. | ||
8 | // | ||
9 | // In Rust, fields are dropped in the declaration order, and we rely on this | ||
10 | // here. We must close input first, so that the `thread` (who holds the | ||
11 | // opposite side of the channel) noticed shutdown. Then, we must join the | ||
12 | // thread, but we must keep out alive so that the thread does not panic. | ||
13 | // | ||
14 | // Note that a potential problem here is that we might drop some messages | ||
15 | // from receiver on the floor. This is ok for rust-analyzer: we have only a | ||
16 | // single client, so, if we are shutting down, nobody is interested in the | ||
17 | // unfinished work anyway! | ||
18 | sender: Sender<I>, | ||
19 | _thread: jod_thread::JoinHandle<()>, | ||
20 | receiver: Receiver<O>, | ||
21 | } | ||
22 | |||
23 | impl<I, O> Worker<I, O> { | ||
24 | pub fn spawn<F>(name: &'static str, buf: usize, f: F) -> Worker<I, O> | ||
25 | where | ||
26 | F: FnOnce(Receiver<I>, Sender<O>) + Send + 'static, | ||
27 | I: Send + 'static, | ||
28 | O: Send + 'static, | ||
29 | { | ||
30 | // Set up worker channels in a deadlock-avoiding way. If one sets both input | ||
31 | // and output buffers to a fixed size, a worker might get stuck. | ||
32 | let (sender, input_receiver) = bounded::<I>(buf); | ||
33 | let (output_sender, receiver) = unbounded::<O>(); | ||
34 | let _thread = jod_thread::Builder::new() | ||
35 | .name(name.to_string()) | ||
36 | .spawn(move || f(input_receiver, output_sender)) | ||
37 | .expect("failed to spawn a thread"); | ||
38 | Worker { sender, _thread, receiver } | ||
39 | } | ||
40 | } | ||
41 | |||
42 | impl<I, O> Worker<I, O> { | ||
43 | pub fn sender(&self) -> &Sender<I> { | ||
44 | &self.sender | ||
45 | } | ||
46 | pub fn receiver(&self) -> &Receiver<O> { | ||
47 | &self.receiver | ||
48 | } | ||
49 | } | ||